Repository: Sevtinge/Cemiuiler Branch: main Commit: b66a0b6fc3e0 Files: 1002 Total size: 3.2 MB Directory structure: gitextract_6q0v22cg/ ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── BUG-REPORT.yml │ │ ├── FEATURE-REQUEST.yml │ │ ├── MIGRATION-REQUEST.yml │ │ └── config.yml │ ├── dependabot.yml │ └── workflows/ │ ├── android.yml │ ├── androidu.yml │ └── crowdin.yml ├── .gitignore ├── LICENSE ├── README.md ├── README_en-US.md ├── README_pt-BR.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── dict.txt │ ├── libs/ │ │ ├── animation-release.aar │ │ ├── appcompat-release.aar │ │ ├── core-release.aar │ │ ├── haptic-release.aar │ │ ├── hyperceiler_expansion_packs-debug.aar │ │ ├── miui-framework.jar │ │ ├── miui.jar │ │ ├── preference-release.aar │ │ ├── smooth-release.aar │ │ └── springback-release.aar │ ├── proguard-log.pro │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── assets/ │ │ └── xposed_init │ ├── java/ │ │ └── com/ │ │ ├── sevtinge/ │ │ │ └── cemiuiler/ │ │ │ ├── Application.java │ │ │ ├── CrashRecord.kt │ │ │ ├── XposedInit.kt │ │ │ ├── callback/ │ │ │ │ └── IAppSelectCallback.java │ │ │ ├── data/ │ │ │ │ ├── AppData.java │ │ │ │ ├── LocationData.java │ │ │ │ ├── ModData.java │ │ │ │ ├── SQLiteHelper.java │ │ │ │ └── adapter/ │ │ │ │ ├── AppDataAdapter.java │ │ │ │ ├── ModSearchAdapter.java │ │ │ │ └── MutipleChoiceAdapter.java │ │ │ ├── module/ │ │ │ │ ├── app/ │ │ │ │ │ ├── AiAsst.java │ │ │ │ │ ├── Aod.java │ │ │ │ │ ├── Barrage.java │ │ │ │ │ ├── Browser.java │ │ │ │ │ ├── Camera.java │ │ │ │ │ ├── Clock.java │ │ │ │ │ ├── ContentExtension.java │ │ │ │ │ ├── Creation.java │ │ │ │ │ ├── Downloads.java │ │ │ │ │ ├── ExternalStorage.java │ │ │ │ │ ├── FileExplorer.java │ │ │ │ │ ├── Gallery.java │ │ │ │ │ ├── GlobalActions.java │ │ │ │ │ ├── GuardProvider.java │ │ │ │ │ ├── Home.java │ │ │ │ │ ├── InCallUi.java │ │ │ │ │ ├── Joyose.java │ │ │ │ │ ├── Lbe.java │ │ │ │ │ ├── Market.java │ │ │ │ │ ├── MediaEditor.java │ │ │ │ │ ├── MiLink.java │ │ │ │ │ ├── MiSettings.java │ │ │ │ │ ├── MiShare.java │ │ │ │ │ ├── MiWallpaper.java │ │ │ │ │ ├── Mirror.java │ │ │ │ │ ├── Mms.java │ │ │ │ │ ├── Mtb.java │ │ │ │ │ ├── Music.java │ │ │ │ │ ├── NetworkBoost.java │ │ │ │ │ ├── Nfc.java │ │ │ │ │ ├── Notes.java │ │ │ │ │ ├── PackageInstaller.java │ │ │ │ │ ├── PersonalAssistant.java │ │ │ │ │ ├── Phone.java │ │ │ │ │ ├── PowerKeeper.java │ │ │ │ │ ├── Scanner.java │ │ │ │ │ ├── ScreenRecorder.java │ │ │ │ │ ├── ScreenShot.java │ │ │ │ │ ├── SecurityCenter.java │ │ │ │ │ ├── Settings.java │ │ │ │ │ ├── SystemFramework.java │ │ │ │ │ ├── SystemFrameworkForCorePatch.java │ │ │ │ │ ├── SystemSettings.java │ │ │ │ │ ├── SystemUI.java │ │ │ │ │ ├── ThemeManager.java │ │ │ │ │ ├── TsmClient.java │ │ │ │ │ ├── Updater.java │ │ │ │ │ ├── Various.java │ │ │ │ │ ├── VoiceAssist.java │ │ │ │ │ └── Weather.java │ │ │ │ ├── base/ │ │ │ │ │ ├── BaseHook.java │ │ │ │ │ ├── BaseModule.java │ │ │ │ │ ├── BaseXposedInit.java │ │ │ │ │ ├── HostDir.kt │ │ │ │ │ └── IXposedHook.java │ │ │ │ └── hook/ │ │ │ │ ├── aiasst/ │ │ │ │ │ └── AiCaptions.kt │ │ │ │ ├── aod/ │ │ │ │ │ └── UnlockAlwaysOnDisplay.kt │ │ │ │ ├── barrage/ │ │ │ │ │ ├── AnyBarrage.kt │ │ │ │ │ └── CustomBarrageLength.kt │ │ │ │ ├── browser/ │ │ │ │ │ └── DebugMode.kt │ │ │ │ ├── camera/ │ │ │ │ │ ├── EnableLabOptions.kt │ │ │ │ │ ├── Unlock120Fps.java │ │ │ │ │ ├── Unlock60Fps.java │ │ │ │ │ ├── UnlockAiEnhance.java │ │ │ │ │ ├── UnlockAiShutter.java │ │ │ │ │ ├── UnlockAiWatermark.java │ │ │ │ │ ├── UnlockAmbilight.java │ │ │ │ │ ├── UnlockAudioZoom.java │ │ │ │ │ ├── UnlockClone.java │ │ │ │ │ ├── UnlockColorEnhance.java │ │ │ │ │ ├── UnlockCosmeticMirror.java │ │ │ │ │ ├── UnlockCvlens.java │ │ │ │ │ ├── UnlockCyberFocusVersion2.java │ │ │ │ │ ├── UnlockDoc.java │ │ │ │ │ ├── UnlockDualcam.java │ │ │ │ │ ├── UnlockDuration.java │ │ │ │ │ ├── UnlockFilm.java │ │ │ │ │ ├── UnlockFilmDelay.java │ │ │ │ │ ├── UnlockFilmDollyZoom.java │ │ │ │ │ ├── UnlockFilmDream.java │ │ │ │ │ ├── UnlockFilmSlowShutter.java │ │ │ │ │ ├── UnlockFilmTimeBackflow.java │ │ │ │ │ ├── UnlockFilmTimeFreeze.java │ │ │ │ │ ├── UnlockHandGesture.java │ │ │ │ │ ├── UnlockHdr.java │ │ │ │ │ ├── UnlockHeic.java │ │ │ │ │ ├── UnlockIdcard.java │ │ │ │ │ ├── UnlockLog.java │ │ │ │ │ ├── UnlockMakeup.java │ │ │ │ │ ├── UnlockMenMakeup.java │ │ │ │ │ ├── UnlockMilive.java │ │ │ │ │ ├── UnlockMoon.java │ │ │ │ │ ├── UnlockNevus.java │ │ │ │ │ ├── UnlockNewBeauty.java │ │ │ │ │ ├── UnlockPano.java │ │ │ │ │ ├── UnlockPixel.java │ │ │ │ │ ├── UnlockPortrait.java │ │ │ │ │ ├── UnlockRaw.java │ │ │ │ │ ├── UnlockSlow.java │ │ │ │ │ ├── UnlockTrackEyes.java │ │ │ │ │ ├── UnlockTrackFeature.java │ │ │ │ │ ├── UnlockTrackFocus.java │ │ │ │ │ ├── UnlockVideosky.java │ │ │ │ │ ├── UnlockVlog.java │ │ │ │ │ └── UnlockVlogPro.java │ │ │ │ ├── clock/ │ │ │ │ │ └── EnableHourGlass.java │ │ │ │ ├── contentextension/ │ │ │ │ │ ├── DoublePress.kt │ │ │ │ │ ├── HorizontalContentExtension.kt │ │ │ │ │ ├── LinkOpenMode.java │ │ │ │ │ ├── SuperImage.kt │ │ │ │ │ ├── UnlockTaplus.kt │ │ │ │ │ └── UseThirdPartyBrowser.java │ │ │ │ ├── creation/ │ │ │ │ │ └── UnlockCreation.kt │ │ │ │ ├── downloads/ │ │ │ │ │ └── FuckXlDownload.java │ │ │ │ ├── externalstorage/ │ │ │ │ │ └── DisableFolderCantUse.java │ │ │ │ ├── fileexplorer/ │ │ │ │ │ └── SelectName.kt │ │ │ │ ├── gallery/ │ │ │ │ │ ├── EnableHdrEnhance.java │ │ │ │ │ ├── EnableIdPhoto.java │ │ │ │ │ ├── EnableMagicMatting.java │ │ │ │ │ ├── EnableMagicSky.java │ │ │ │ │ ├── EnableOcr.java │ │ │ │ │ ├── EnableOcrForm.java │ │ │ │ │ ├── EnablePdf.java │ │ │ │ │ ├── EnablePhotoMovie.java │ │ │ │ │ ├── EnableRemover2.java │ │ │ │ │ ├── EnableTextYanhua.java │ │ │ │ │ ├── EnableVideoEditor.java │ │ │ │ │ └── EnableVideoPost.java │ │ │ │ ├── guardprovider/ │ │ │ │ │ ├── DisableUploadAppList.java │ │ │ │ │ └── DisableUploadAppListNew.kt │ │ │ │ ├── home/ │ │ │ │ │ ├── AllAppsBlur.java │ │ │ │ │ ├── AnimDurationRatio.kt │ │ │ │ │ ├── FreeFormCountForHome.java │ │ │ │ │ ├── HideNavigationBar.java │ │ │ │ │ ├── HomePortraitReverse.java │ │ │ │ │ ├── MaxFreeForm.kt │ │ │ │ │ ├── ScreenSwipe.java │ │ │ │ │ ├── SeekPoints.java │ │ │ │ │ ├── SetDeviceLevel.kt │ │ │ │ │ ├── StickyFloatingWindowsForHome.java │ │ │ │ │ ├── ToastSlideAgain.java │ │ │ │ │ ├── UnlockHotseatIcon.kt │ │ │ │ │ ├── UserPresentAnimation.java │ │ │ │ │ ├── WidgetCornerRadius.java │ │ │ │ │ ├── WidgetCrack.java │ │ │ │ │ ├── dock/ │ │ │ │ │ │ ├── DisableRecentsIcon.kt │ │ │ │ │ │ ├── DockCustom.java │ │ │ │ │ │ ├── FoldDeviceDock.kt │ │ │ │ │ │ ├── FoldDock.java │ │ │ │ │ │ ├── HideSeekPoint.kt │ │ │ │ │ │ └── ShowDockIconTitle.kt │ │ │ │ │ ├── drawer/ │ │ │ │ │ │ ├── AllAppsContainerViewBlur.kt │ │ │ │ │ │ ├── AppDrawer.kt │ │ │ │ │ │ └── PinyinArrangement.java │ │ │ │ │ ├── folder/ │ │ │ │ │ │ ├── BigFolderIcon.java │ │ │ │ │ │ ├── BigFolderIconBlur.java │ │ │ │ │ │ ├── BigFolderIconBlur1x2.java │ │ │ │ │ │ ├── BigFolderIconBlur2x1.java │ │ │ │ │ │ ├── BigFolderItemMaxCount.java │ │ │ │ │ │ ├── FolderAnimation.kt │ │ │ │ │ │ ├── FolderAutoClose.kt │ │ │ │ │ │ ├── FolderBlur.kt │ │ │ │ │ │ ├── FolderColumns.kt │ │ │ │ │ │ ├── FolderShade.java │ │ │ │ │ │ ├── FolderVerticalPadding.kt │ │ │ │ │ │ └── SmallFolderIconBlur.java │ │ │ │ │ ├── gesture/ │ │ │ │ │ │ ├── DoubleTap.java │ │ │ │ │ │ ├── DoubleTapController.kt │ │ │ │ │ │ ├── HotSeatSwipe.java │ │ │ │ │ │ ├── QuickBack.java │ │ │ │ │ │ ├── ShakeDevice.java │ │ │ │ │ │ └── SwipeAndStop.java │ │ │ │ │ ├── layout/ │ │ │ │ │ │ ├── HotSeatsHeight.java │ │ │ │ │ │ ├── HotSeatsMarginBottom.java │ │ │ │ │ │ ├── HotSeatsMarginTop.java │ │ │ │ │ │ ├── SearchBarMarginBottom.java │ │ │ │ │ │ ├── ShowClock.java │ │ │ │ │ │ ├── UnlockGrids.java │ │ │ │ │ │ ├── UnlockGridsNoWord.java │ │ │ │ │ │ └── WorkspacePadding.java │ │ │ │ │ ├── mipad/ │ │ │ │ │ │ ├── EnableHideGestureLine.kt │ │ │ │ │ │ ├── EnableMoreSetting.kt │ │ │ │ │ │ └── SetGestureNeedFingerNum.kt │ │ │ │ │ ├── navigation/ │ │ │ │ │ │ ├── BackGestureAreaHeight.java │ │ │ │ │ │ └── BackGestureAreaWidth.java │ │ │ │ │ ├── other/ │ │ │ │ │ │ ├── AlwaysBlurWallpaper.kt │ │ │ │ │ │ ├── AlwaysShowStatusClock.kt │ │ │ │ │ │ ├── BlurRadius.kt │ │ │ │ │ │ ├── BlurWhenShowShortcutMenu.kt │ │ │ │ │ │ ├── DisableHideGoogle.kt │ │ │ │ │ │ ├── FixAndroidRS.kt │ │ │ │ │ │ ├── FreeformShortcutMenu.java │ │ │ │ │ │ ├── HomeMode.java │ │ │ │ │ │ ├── InfiniteScroll.java │ │ │ │ │ │ ├── OverlapMode.kt │ │ │ │ │ │ ├── ShortcutBackgroundBlur.kt │ │ │ │ │ │ ├── ShortcutItemCount.kt │ │ │ │ │ │ └── ShowAllHideApp.kt │ │ │ │ │ ├── recent/ │ │ │ │ │ │ ├── AlwaysShowCleanUp.kt │ │ │ │ │ │ ├── BlurLevel.kt │ │ │ │ │ │ ├── CardTextColor.kt │ │ │ │ │ │ ├── CardTextSize.kt │ │ │ │ │ │ ├── DisableRecentViewWallpaperDarken.kt │ │ │ │ │ │ ├── FreeformCardBackgroundColor.kt │ │ │ │ │ │ ├── HideCleanUp.kt │ │ │ │ │ │ ├── HideFreeform.kt │ │ │ │ │ │ ├── HideStatusBarWhenEnterRecent.kt │ │ │ │ │ │ ├── MemInfoShow.kt │ │ │ │ │ │ ├── RealMemory.kt │ │ │ │ │ │ ├── RecentResource.kt │ │ │ │ │ │ ├── RecentText.kt │ │ │ │ │ │ ├── RemoveCardAnim.kt │ │ │ │ │ │ ├── RemoveIcon.kt │ │ │ │ │ │ ├── TaskViewHorizontal.kt │ │ │ │ │ │ └── TaskViewVertical.kt │ │ │ │ │ ├── title/ │ │ │ │ │ │ ├── AnimParamCustom.java │ │ │ │ │ │ ├── BigIconCorner.kt │ │ │ │ │ │ ├── DisableHideFile.kt │ │ │ │ │ │ ├── DisableHideTheme.kt │ │ │ │ │ │ ├── DownloadAnimation.java │ │ │ │ │ │ ├── EnableIconMonetColor.kt │ │ │ │ │ │ ├── EnableIconMonoChrome.java │ │ │ │ │ │ ├── FixAnimation.java │ │ │ │ │ │ ├── HiddenAllTitle.java │ │ │ │ │ │ ├── IconScaleHook.java │ │ │ │ │ │ ├── IconTitleColor.kt │ │ │ │ │ │ ├── LargeIconCornerRadius.java │ │ │ │ │ │ ├── NewInstallIndicator.java │ │ │ │ │ │ ├── PerfectIcon.java │ │ │ │ │ │ ├── TitleFontSize.java │ │ │ │ │ │ └── TitleMarquee.java │ │ │ │ │ └── widget/ │ │ │ │ │ ├── AllWidgetAnimation.java │ │ │ │ │ ├── AllowMoveAllWidgetToMinus.kt │ │ │ │ │ ├── AlwaysShowMiuiWidget.kt │ │ │ │ │ ├── HideWidgetTitles.kt │ │ │ │ │ └── ResizableWidgets.kt │ │ │ │ ├── incallui/ │ │ │ │ │ ├── AnswerInHeadUp.java │ │ │ │ │ └── HideCrbt.java │ │ │ │ ├── joyose/ │ │ │ │ │ ├── DisableCloudControl.java │ │ │ │ │ ├── DisableCloudControl.kt │ │ │ │ │ ├── EnableGpuTuner.java │ │ │ │ │ └── EnableGpuTuner.kt │ │ │ │ ├── lbe/ │ │ │ │ │ └── DisableClipboardTip.kt │ │ │ │ ├── market/ │ │ │ │ │ ├── DeviceModify.java │ │ │ │ │ └── NewIcon.java │ │ │ │ ├── mediaeditor/ │ │ │ │ │ ├── FilterManagerAll.kt │ │ │ │ │ └── UnlockMinimumCropLimitNew.kt │ │ │ │ ├── milink/ │ │ │ │ │ └── UnlockMiShare.java │ │ │ │ ├── mirror/ │ │ │ │ │ └── UnlockMiuiPlus.java │ │ │ │ ├── misettings/ │ │ │ │ │ ├── CustomRefreshRate.kt │ │ │ │ │ └── ShowMoreFpsList.kt │ │ │ │ ├── mishare/ │ │ │ │ │ ├── NoAutoTurnOff.kt │ │ │ │ │ └── UnlockTurboMode.kt │ │ │ │ ├── miwallpaper/ │ │ │ │ │ └── UnlockSuperWallpaper.java │ │ │ │ ├── mms/ │ │ │ │ │ └── DisableAd.kt │ │ │ │ ├── mtb/ │ │ │ │ │ ├── BypassAuthentication.kt │ │ │ │ │ └── IsUserBuild.kt │ │ │ │ ├── music/ │ │ │ │ │ └── DisableAd.java │ │ │ │ ├── networkboost/ │ │ │ │ │ └── LinkTurboToast.java │ │ │ │ ├── nfc/ │ │ │ │ │ ├── AllowInformationScreen.kt │ │ │ │ │ └── DisableSound.java │ │ │ │ ├── packageinstaller/ │ │ │ │ │ ├── AllAsSystemApp.kt │ │ │ │ │ ├── DisableAD.kt │ │ │ │ │ ├── DisableCountChecking.kt │ │ │ │ │ ├── DisableSafeModelTip.kt │ │ │ │ │ ├── DisplayMoreApkInfo.java │ │ │ │ │ ├── DisplayMoreApkInfoNew.kt │ │ │ │ │ ├── InstallRiskDisable.kt │ │ │ │ │ ├── InstallSource.java │ │ │ │ │ ├── MiuiPackageInstallModify.java │ │ │ │ │ ├── SafeMode.java │ │ │ │ │ └── UpdateSystemApp.java │ │ │ │ ├── personalassistant/ │ │ │ │ │ ├── BlurOverlay.java │ │ │ │ │ ├── BlurPersonalAssistant.kt │ │ │ │ │ ├── BlurPersonalAssistantBackGround.kt │ │ │ │ │ ├── EnableFoldWidget.java │ │ │ │ │ ├── PadWidgetEnable.java │ │ │ │ │ └── WidgetCrack.kt │ │ │ │ ├── phone/ │ │ │ │ │ ├── DualNrSupport.kt │ │ │ │ │ ├── DualSaSupport.kt │ │ │ │ │ ├── ModemFeature.kt │ │ │ │ │ ├── N1BandPhone.kt │ │ │ │ │ ├── N28BandPhone.kt │ │ │ │ │ ├── N5N8BandPhone.kt │ │ │ │ │ └── ViceSlotVolteButton.kt │ │ │ │ ├── powerkeeper/ │ │ │ │ │ ├── CustomRefreshRate.kt │ │ │ │ │ ├── DontKillApps.kt │ │ │ │ │ ├── LockMaxFps.kt │ │ │ │ │ └── PreventBatteryWitelist.java │ │ │ │ ├── scanner/ │ │ │ │ │ ├── EnableCard.java │ │ │ │ │ ├── EnableDocPpt.java │ │ │ │ │ ├── EnableOcr.java │ │ │ │ │ ├── EnableTranslation.java │ │ │ │ │ └── document/ │ │ │ │ │ ├── EnableDocument.java │ │ │ │ │ ├── EnableExcel.java │ │ │ │ │ └── EnablePpt.java │ │ │ │ ├── screenrecorder/ │ │ │ │ │ ├── ForceSupportPlaybackCapture.kt │ │ │ │ │ ├── SaveToMovies.kt │ │ │ │ │ ├── ScreenRecorderConfig.kt │ │ │ │ │ └── UnlockMoreVolumeFrom.java │ │ │ │ ├── screenshot/ │ │ │ │ │ ├── DeviceShellCustomize.kt │ │ │ │ │ ├── SaveToPictures.kt │ │ │ │ │ ├── UnlockMinimumCropLimit.kt │ │ │ │ │ └── UnlockPrivacyMarking.kt │ │ │ │ ├── securitycenter/ │ │ │ │ │ ├── AppLockPinScramble.java │ │ │ │ │ ├── BlurSecurity.kt │ │ │ │ │ ├── DisableReport.kt │ │ │ │ │ ├── GetBubbleAppString.kt │ │ │ │ │ ├── IsSbnBelongToActiveBubbleApp.kt │ │ │ │ │ ├── NewBoxBlur.java │ │ │ │ │ ├── RemoveConversationBubbleSettingsRestriction.kt │ │ │ │ │ ├── RemoveOpenAppConfirmationPopup.kt │ │ │ │ │ ├── SidebarLineCustom.kt │ │ │ │ │ ├── VideoDolbyOpen.java │ │ │ │ │ ├── app/ │ │ │ │ │ │ ├── AppDefaultSort.java │ │ │ │ │ │ ├── AppDetails.java │ │ │ │ │ │ ├── AppDisable.java │ │ │ │ │ │ ├── AppRestrict.java │ │ │ │ │ │ └── OpenByDefaultSetting.kt │ │ │ │ │ ├── battery/ │ │ │ │ │ │ ├── ScreenUsedTime.kt │ │ │ │ │ │ ├── ShowBatteryTemperature.java │ │ │ │ │ │ ├── ShowBatteryTemperatureNew.kt │ │ │ │ │ │ ├── UnlockSmartCharge.kt │ │ │ │ │ │ └── UnlockSuperWirelessCharge.kt │ │ │ │ │ ├── beauty/ │ │ │ │ │ │ ├── BeautyFace.kt │ │ │ │ │ │ ├── BeautyLightAuto.kt │ │ │ │ │ │ ├── BeautyPc.kt │ │ │ │ │ │ └── BeautyPrivacy.kt │ │ │ │ │ ├── lab/ │ │ │ │ │ │ ├── AiClipboardEnable.kt │ │ │ │ │ │ ├── BlurLocationEnable.kt │ │ │ │ │ │ ├── GetNumberEnable.kt │ │ │ │ │ │ └── LabUtilsClass.kt │ │ │ │ │ ├── other/ │ │ │ │ │ │ ├── DisableRootCheck.kt │ │ │ │ │ │ ├── FuckRiskPkg.kt │ │ │ │ │ │ ├── LockOneHundredPoints.kt │ │ │ │ │ │ ├── NoLowBatteryWarning.kt │ │ │ │ │ │ └── SkipCountDownLimit.java │ │ │ │ │ └── sidebar/ │ │ │ │ │ ├── AddSideBarExpandReceiver.java │ │ │ │ │ ├── DisableDockSuggest.java │ │ │ │ │ ├── game/ │ │ │ │ │ │ ├── RemoveMacroBlackList.kt │ │ │ │ │ │ └── UnlockGunService.kt │ │ │ │ │ └── video/ │ │ │ │ │ ├── DisableRemoveScreenHoldOn.kt │ │ │ │ │ ├── UnlockEnhanceContours.kt │ │ │ │ │ ├── UnlockMemc.kt │ │ │ │ │ └── UnlockSuperResolution.kt │ │ │ │ ├── settings/ │ │ │ │ │ ├── CemiuilerSettings.java │ │ │ │ │ ├── NotificationImportance.java │ │ │ │ │ └── VolumeSeparateControlForSettings.java │ │ │ │ ├── systemframework/ │ │ │ │ │ ├── AllRotations.java │ │ │ │ │ ├── AllowUninstall.java │ │ │ │ │ ├── AllowUntrustedTouch.java │ │ │ │ │ ├── AppDisableService.java │ │ │ │ │ ├── AppLinkVerify.java │ │ │ │ │ ├── BackgroundBlurDrawable.kt │ │ │ │ │ ├── CleanOpenMenu.java │ │ │ │ │ ├── CleanShareMenu.java │ │ │ │ │ ├── DeleteOnPostNotification.kt │ │ │ │ │ ├── DisableCleaner.kt │ │ │ │ │ ├── DisableFreeformBlackList.java │ │ │ │ │ ├── DisablePinVerifyPer72h.java │ │ │ │ │ ├── FlagSecure.java │ │ │ │ │ ├── FreeFormCount.kt │ │ │ │ │ ├── FreeformBubble.java │ │ │ │ │ ├── LocationSimulation.java │ │ │ │ │ ├── MultiFreeFormSupported.kt │ │ │ │ │ ├── PackagePermissions.java │ │ │ │ │ ├── RemoveSmallWindowRestrictions.kt │ │ │ │ │ ├── ScreenRotation.java │ │ │ │ │ ├── SpeedInstall.java │ │ │ │ │ ├── StickyFloatingWindows.java │ │ │ │ │ ├── ThemeProvider.kt │ │ │ │ │ ├── ThermalBrightness.java │ │ │ │ │ ├── UseOriginalAnimation.java │ │ │ │ │ ├── VolumeDefaultStream.java │ │ │ │ │ ├── VolumeDisableSafe.java │ │ │ │ │ ├── VolumeFirstPress.java │ │ │ │ │ ├── VolumeMediaSteps.kt │ │ │ │ │ ├── VolumeSeparateControl.java │ │ │ │ │ ├── VolumeSteps.java │ │ │ │ │ ├── corepatch/ │ │ │ │ │ │ ├── BypassSignCheckForT.kt │ │ │ │ │ │ ├── CorePatchForR.java │ │ │ │ │ │ ├── CorePatchForS.java │ │ │ │ │ │ ├── CorePatchForT.java │ │ │ │ │ │ ├── CorePatchForU.java │ │ │ │ │ │ ├── ReturnConstant.java │ │ │ │ │ │ └── XposedHelper.java │ │ │ │ │ ├── display/ │ │ │ │ │ │ ├── AutoBrightness.java │ │ │ │ │ │ ├── DisplayCutout.kt │ │ │ │ │ │ └── ToastTime.java │ │ │ │ │ ├── freeform/ │ │ │ │ │ │ └── OpenAppInFreeForm.java │ │ │ │ │ ├── mipad/ │ │ │ │ │ │ ├── IgnoreStylusKeyGesture.kt │ │ │ │ │ │ ├── NoMagicPointer.kt │ │ │ │ │ │ ├── RemoveStylusBluetoothRestriction.kt │ │ │ │ │ │ ├── RestoreEsc.kt │ │ │ │ │ │ └── SetGestureNeedFingerNum.kt │ │ │ │ │ └── network/ │ │ │ │ │ ├── DualNRSupport.kt │ │ │ │ │ ├── DualSASupport.kt │ │ │ │ │ ├── N1Band.kt │ │ │ │ │ ├── N28Band.kt │ │ │ │ │ └── N5N8Band.kt │ │ │ │ ├── systemsettings/ │ │ │ │ │ ├── AddMiuiPlusEntry.java │ │ │ │ │ ├── AppsFreezerEnable.java │ │ │ │ │ ├── EnableFoldArea.kt │ │ │ │ │ ├── EnablePadArea.kt │ │ │ │ │ ├── EnableSpeedMode.java │ │ │ │ │ ├── InternationalBuild.java │ │ │ │ │ ├── NewNFCPage.java │ │ │ │ │ ├── NoveltyHaptic.kt │ │ │ │ │ ├── QuickManageOverlayPermission.kt │ │ │ │ │ ├── QuickManageUnknownAppSources.kt │ │ │ │ │ ├── UnLockAreaScreenshot.kt │ │ │ │ │ ├── UnlockTaplusForSettings.kt │ │ │ │ │ ├── ViewWifiPasswordHook.java │ │ │ │ │ ├── VoipAssistantController.java │ │ │ │ │ └── aiimage/ │ │ │ │ │ ├── UnlockAi.java │ │ │ │ │ ├── UnlockMemc.java │ │ │ │ │ └── UnlockSuperResolution.java │ │ │ │ ├── systemui/ │ │ │ │ │ ├── AutoCollapse.java │ │ │ │ │ ├── BatteryIndicator.java │ │ │ │ │ ├── BluetoothRestrict.java │ │ │ │ │ ├── ChargeAnimationStyle.java │ │ │ │ │ ├── ClockCenterHook.java │ │ │ │ │ ├── EnableVolumeBlur.kt │ │ │ │ │ ├── HideNavigationBar.java │ │ │ │ │ ├── MiuiGxzwSize.java │ │ │ │ │ ├── MonetThemeOverlay.java │ │ │ │ │ ├── NotificationFix.java │ │ │ │ │ ├── NotificationFreeform.java │ │ │ │ │ ├── NotificationVolumeSeparateSlider.java │ │ │ │ │ ├── OriginChargeAnimation.java │ │ │ │ │ ├── QSDetailBackGround.java │ │ │ │ │ ├── QSLabelsHook.java │ │ │ │ │ ├── ShouldPlayUnmuteSoundHook.java │ │ │ │ │ ├── StatusBarActions.java │ │ │ │ │ ├── SwitchControlPanel.java │ │ │ │ │ ├── UseNativeRecents.java │ │ │ │ │ ├── VolumeTimerValuesHook.java │ │ │ │ │ ├── controlcenter/ │ │ │ │ │ │ ├── AddBlurEffectToNotificationView.kt │ │ │ │ │ │ ├── BluetoothTileStyle.java │ │ │ │ │ │ ├── CCGrid.kt │ │ │ │ │ │ ├── CompactNotificationsHook.kt │ │ │ │ │ │ ├── ControlCenterStyle.kt │ │ │ │ │ │ ├── FiveGTile.java │ │ │ │ │ │ ├── FixMediaControlPanel.kt │ │ │ │ │ │ ├── FlashLight.java │ │ │ │ │ │ ├── GmsTile.java │ │ │ │ │ │ ├── MuteVisibleNotifications.java │ │ │ │ │ │ ├── NotificationWeather.kt │ │ │ │ │ │ ├── NotificationWeatherNew.kt │ │ │ │ │ │ ├── NotificationWeatherOld.kt │ │ │ │ │ │ ├── QQSGrid.kt │ │ │ │ │ │ ├── QQSGridOld.java │ │ │ │ │ │ ├── QSControlDetailBackgroundAlpha.kt │ │ │ │ │ │ ├── QSGrid.kt │ │ │ │ │ │ ├── QSGridLabels.java │ │ │ │ │ │ ├── QSGridOld.java │ │ │ │ │ │ ├── RedirectToNotificationChannelSetting.kt │ │ │ │ │ │ ├── SmartHome.java │ │ │ │ │ │ ├── SunlightMode.java │ │ │ │ │ │ └── SwitchCCAndNotification.java │ │ │ │ │ ├── lockscreen/ │ │ │ │ │ │ ├── AddBlurEffectToLockScreen.kt │ │ │ │ │ │ ├── BlurButton.kt │ │ │ │ │ │ ├── ChargingCVP.kt │ │ │ │ │ │ ├── ClockDisplaySeconds.kt │ │ │ │ │ │ ├── ForceClockUseSystemFontsHook.kt │ │ │ │ │ │ ├── HideLockScreenHint.kt │ │ │ │ │ │ ├── HideLockScreenStatusBar.kt │ │ │ │ │ │ ├── HideLockscreenZenMode.kt │ │ │ │ │ │ ├── LockScreenDoubleTapToSleep.kt │ │ │ │ │ │ ├── NoPassword.kt │ │ │ │ │ │ ├── RemoveCamera.kt │ │ │ │ │ │ ├── RemoveSmartScreen.kt │ │ │ │ │ │ └── ScramblePIN.java │ │ │ │ │ ├── navigation/ │ │ │ │ │ │ ├── HandleLineCustom.kt │ │ │ │ │ │ └── NavigationCustom.java │ │ │ │ │ ├── plugin/ │ │ │ │ │ │ ├── EnableVolumeBlur.java │ │ │ │ │ │ ├── HideDeviceControlEntry.java │ │ │ │ │ │ ├── HideMiPlayEntry.java │ │ │ │ │ │ ├── HideMiSmartHubEntry.java │ │ │ │ │ │ └── PluginHelper.java │ │ │ │ │ └── statusbar/ │ │ │ │ │ ├── BigMobileNetworkType.java │ │ │ │ │ ├── DisplayHardwareDetail.java │ │ │ │ │ ├── DoubleTapToSleep.kt │ │ │ │ │ ├── DualRowSignalHook.java │ │ │ │ │ ├── HideStatusBarBeforeScreenshot.java │ │ │ │ │ ├── MobileNetwork.java │ │ │ │ │ ├── NotificationIconColumns.kt │ │ │ │ │ ├── SelectiveHideIconForAlarmClock.java │ │ │ │ │ ├── WifiStandard.java │ │ │ │ │ ├── clock/ │ │ │ │ │ │ ├── TimeCustomization.kt │ │ │ │ │ │ └── TimeStyle.kt │ │ │ │ │ ├── icon/ │ │ │ │ │ │ ├── all/ │ │ │ │ │ │ │ ├── BatteryStyle.kt │ │ │ │ │ │ │ ├── BluetoothIcon.java │ │ │ │ │ │ │ ├── DataSaverIcon.java │ │ │ │ │ │ │ ├── HideBatteryIcon.kt │ │ │ │ │ │ │ ├── HideVoWiFiIcon.kt │ │ │ │ │ │ │ ├── IconsFromSystemManager.kt │ │ │ │ │ │ │ ├── StatusBarIcon.kt │ │ │ │ │ │ │ ├── StatusBarIconPositionAdjust.java │ │ │ │ │ │ │ ├── StatusBarSimIcon.kt │ │ │ │ │ │ │ └── WifiNetworkIndicator.kt │ │ │ │ │ │ └── t/ │ │ │ │ │ │ └── UseNewHD.kt │ │ │ │ │ ├── layout/ │ │ │ │ │ │ └── StatusBarLayout.kt │ │ │ │ │ ├── model/ │ │ │ │ │ │ ├── MobileTypeSingleHook.kt │ │ │ │ │ │ └── MobileTypeTextCustom.kt │ │ │ │ │ └── network/ │ │ │ │ │ ├── NetworkSpeed.kt │ │ │ │ │ ├── NetworkSpeedSec.kt │ │ │ │ │ ├── NetworkSpeedSpacing.kt │ │ │ │ │ ├── NetworkSpeedStyle.kt │ │ │ │ │ ├── StatusBarNoNetSpeedSep.kt │ │ │ │ │ └── s/ │ │ │ │ │ └── NetworkSpeedWidth.kt │ │ │ │ ├── thememanager/ │ │ │ │ │ ├── DisableThemeAd.java │ │ │ │ │ ├── DisableThemeAdNew.kt │ │ │ │ │ ├── EnableFoldTheme.java │ │ │ │ │ ├── EnablePadTheme.java │ │ │ │ │ ├── ThemeCrackNew.kt │ │ │ │ │ └── VersionCodeModify.java │ │ │ │ ├── tsmclient/ │ │ │ │ │ └── AutoNfc.kt │ │ │ │ ├── updater/ │ │ │ │ │ ├── DeviceModify.kt │ │ │ │ │ ├── VabUpdate.kt │ │ │ │ │ ├── VersionCodeModify.java │ │ │ │ │ └── VersionCodeNew.kt │ │ │ │ ├── various/ │ │ │ │ │ ├── CollapseMiuiTitle.java │ │ │ │ │ ├── DialogBlur.java │ │ │ │ │ ├── DialogCustom.java │ │ │ │ │ ├── DialogGravity.java │ │ │ │ │ ├── MiuiAppNoOverScroll.java │ │ │ │ │ ├── NoAccessDeviceLogsRequest.kt │ │ │ │ │ ├── NotificationBlur.java │ │ │ │ │ ├── UnlockIme.kt │ │ │ │ │ └── UnlockSuperClipboard.kt │ │ │ │ ├── voiceassist/ │ │ │ │ │ └── UseThirdPartyBrowser.kt │ │ │ │ └── weather/ │ │ │ │ └── SetDeviceLevel.java │ │ │ ├── prefs/ │ │ │ │ └── PreferenceHeader.java │ │ │ ├── provider/ │ │ │ │ └── SharedPrefsProvider.java │ │ │ ├── ui/ │ │ │ │ ├── CustomHookActivity.java │ │ │ │ ├── HideAppActivity.java │ │ │ │ ├── MainActivity.java │ │ │ │ ├── ModuleSettingsActivity.java │ │ │ │ ├── SubPickerActivity.java │ │ │ │ ├── SubSettings.java │ │ │ │ ├── base/ │ │ │ │ │ ├── BaseSettingsActivity.java │ │ │ │ │ ├── BaseSettingsProxy.java │ │ │ │ │ ├── SettingsActivity.java │ │ │ │ │ └── SettingsProxy.java │ │ │ │ ├── customhook/ │ │ │ │ │ └── CustomHookConfigActivity.java │ │ │ │ ├── fragment/ │ │ │ │ │ ├── AboutFragment.kt │ │ │ │ │ ├── AiAsstFragment.java │ │ │ │ │ ├── AodFragment.java │ │ │ │ │ ├── BarrageFragment.java │ │ │ │ │ ├── BrowserFragment.java │ │ │ │ │ ├── CameraFragment.java │ │ │ │ │ ├── ClockFragment.java │ │ │ │ │ ├── ContentExtensionFragment.java │ │ │ │ │ ├── CreationFragment.java │ │ │ │ │ ├── DownloadsFragment.java │ │ │ │ │ ├── FileExplorerFragment.java │ │ │ │ │ ├── GalleryFragment.java │ │ │ │ │ ├── GuardProviderFragment.java │ │ │ │ │ ├── HomeFragment.java │ │ │ │ │ ├── InCallUiFragment.java │ │ │ │ │ ├── JoyoseFragment.java │ │ │ │ │ ├── LbeFragment.java │ │ │ │ │ ├── MainFragment.java │ │ │ │ │ ├── MarketFragment.java │ │ │ │ │ ├── MediaEditorFragment.java │ │ │ │ │ ├── MiLinkFragment.java │ │ │ │ │ ├── MiSettingsFragment.java │ │ │ │ │ ├── MiShareFragment.java │ │ │ │ │ ├── MiWallpaperFragment.java │ │ │ │ │ ├── MirrorFragment.java │ │ │ │ │ ├── MiuiPackageInstallerFragment.java │ │ │ │ │ ├── MmsFragment.java │ │ │ │ │ ├── ModuleSettingsFragment.java │ │ │ │ │ ├── MtbFragment.java │ │ │ │ │ ├── MusicFragment.java │ │ │ │ │ ├── NetworkBoostFragment.java │ │ │ │ │ ├── NfcFragment.java │ │ │ │ │ ├── PersonalAssistantFragment.java │ │ │ │ │ ├── PhoneFragment.java │ │ │ │ │ ├── PowerKeeperFragment.java │ │ │ │ │ ├── ScannerFragment.java │ │ │ │ │ ├── ScreenRecorderFragment.java │ │ │ │ │ ├── ScreenShotFragment.java │ │ │ │ │ ├── SecurityCenterFragment.java │ │ │ │ │ ├── SystemFrameworkFragment.java │ │ │ │ │ ├── SystemSettingsFragment.java │ │ │ │ │ ├── SystemUIFragment.java │ │ │ │ │ ├── ThemeManagerFragment.java │ │ │ │ │ ├── TsmClientFragment.java │ │ │ │ │ ├── UpdaterFragment.java │ │ │ │ │ ├── VariousFragment.java │ │ │ │ │ ├── WeatherFragment.java │ │ │ │ │ ├── about/ │ │ │ │ │ │ ├── AboutContributerFragment.java │ │ │ │ │ │ └── AboutUseFragment.java │ │ │ │ │ ├── base/ │ │ │ │ │ │ ├── BasePreferenceFragment.java │ │ │ │ │ │ └── SettingsPreferenceFragment.java │ │ │ │ │ ├── framework/ │ │ │ │ │ │ ├── DisplaySettings.java │ │ │ │ │ │ ├── FreeFormSettings.java │ │ │ │ │ │ ├── NetworkSettings.java │ │ │ │ │ │ ├── OtherSettings.java │ │ │ │ │ │ └── VolumeSettings.java │ │ │ │ │ ├── home/ │ │ │ │ │ │ ├── HomeDockSettings.java │ │ │ │ │ │ ├── HomeDrawerSettings.java │ │ │ │ │ │ ├── HomeFolderSettings.java │ │ │ │ │ │ ├── HomeGestureSettings.java │ │ │ │ │ │ ├── HomeLayoutSettings.java │ │ │ │ │ │ ├── HomeOtherSettings.java │ │ │ │ │ │ ├── HomeRecentSettings.java │ │ │ │ │ │ ├── HomeTitleAnimSettings.java │ │ │ │ │ │ ├── HomeTitleSettings.java │ │ │ │ │ │ ├── HomeWidgetSettings.java │ │ │ │ │ │ └── anim/ │ │ │ │ │ │ ├── HomeTitleAnim1Settings.java │ │ │ │ │ │ ├── HomeTitleAnim2Settings.java │ │ │ │ │ │ ├── HomeTitleAnim3Settings.java │ │ │ │ │ │ ├── HomeTitleAnim4Settings.java │ │ │ │ │ │ ├── HomeTitleAnim5Settings.java │ │ │ │ │ │ ├── HomeTitleAnim6Settings.java │ │ │ │ │ │ ├── HomeTitleAnim7Settings.java │ │ │ │ │ │ └── HomeTitleAnim8Settings.java │ │ │ │ │ ├── settings/ │ │ │ │ │ │ └── SafeModeFragment.java │ │ │ │ │ ├── sub/ │ │ │ │ │ │ ├── AppPicker.java │ │ │ │ │ │ ├── CustomBackgroundSettings.java │ │ │ │ │ │ └── MultiActionSettings.java │ │ │ │ │ ├── systemui/ │ │ │ │ │ │ ├── ControlCenterSettings.java │ │ │ │ │ │ ├── LockScreenSettings.java │ │ │ │ │ │ ├── NavigationSettings.java │ │ │ │ │ │ ├── StatusBarSettings.java │ │ │ │ │ │ ├── SystemUIOtherSettings.java │ │ │ │ │ │ └── statusbar/ │ │ │ │ │ │ ├── BatteryDetailIndicatorSettings.java │ │ │ │ │ │ ├── BatteryIndicatorSettings.java │ │ │ │ │ │ ├── BatteryStyleSettings.java │ │ │ │ │ │ ├── ClockIndicatorSettings.java │ │ │ │ │ │ ├── DoubleLineNetworkSettings.java │ │ │ │ │ │ ├── IconManageSettings.java │ │ │ │ │ │ ├── MobileNetworkTypeSettings.java │ │ │ │ │ │ └── NetworkSpeedIndicatorSettings.java │ │ │ │ │ └── various/ │ │ │ │ │ ├── AOSPSettings.java │ │ │ │ │ ├── AlertDialogSettings.java │ │ │ │ │ └── MiPadSettings.java │ │ │ │ └── various/ │ │ │ │ ├── LocationDataActivity.java │ │ │ │ ├── LocationSimulationActivity.java │ │ │ │ └── fragment/ │ │ │ │ └── VariousFragment.java │ │ │ ├── utils/ │ │ │ │ ├── BackupUtils.java │ │ │ │ ├── BitmapUtils.java │ │ │ │ ├── BlurUtils.java │ │ │ │ ├── ColorUtils.kt │ │ │ │ ├── ColorUtilsStatic.java │ │ │ │ ├── CtaUtils.java │ │ │ │ ├── DexKit.kt │ │ │ │ ├── DialogHelper.java │ │ │ │ ├── DisplayUtils.java │ │ │ │ ├── Helpers.java │ │ │ │ ├── HookUtils.kt │ │ │ │ ├── KotlinXposedHelper.kt │ │ │ │ ├── LogcatHelper.java │ │ │ │ ├── MathUtils.java │ │ │ │ ├── PrefsMap.java │ │ │ │ ├── PrefsUtils.java │ │ │ │ ├── PropertyUtils.kt │ │ │ │ ├── ResourcesHook.java │ │ │ │ ├── SearchHelper.java │ │ │ │ ├── SettingLauncher.java │ │ │ │ ├── SettingLauncherHelper.java │ │ │ │ ├── ShakeManager.java │ │ │ │ ├── ShellUtils.java │ │ │ │ ├── SystemProperties.kt │ │ │ │ ├── TileUtils.java │ │ │ │ ├── ToastHelper.java │ │ │ │ ├── XposedUtils.java │ │ │ │ ├── api/ │ │ │ │ │ ├── LinQiqiApis.kt │ │ │ │ │ ├── VoyagerApis.kt │ │ │ │ │ └── loadClassByLazy.kt │ │ │ │ ├── devicesdk/ │ │ │ │ │ ├── AppUtils.kt │ │ │ │ │ └── SystemSDK.kt │ │ │ │ └── log/ │ │ │ │ ├── AndroidLogUtils.java │ │ │ │ ├── XposedLogUtils.java │ │ │ │ └── XposedLogUtilsKt.kt │ │ │ └── view/ │ │ │ ├── BatteryIndicatorView.java │ │ │ ├── BlurFrameLayout.java │ │ │ ├── CircleImageView.java │ │ │ ├── MultipleChoiceView.java │ │ │ ├── RestartAlertDialog.java │ │ │ ├── SpinnerEx.java │ │ │ ├── WeatherData.kt │ │ │ └── WeatherView.kt │ │ └── zhenxiang/ │ │ └── blur/ │ │ ├── BackgroundBlurDrawableExtensions.kt │ │ ├── BlurFrameLayout.kt │ │ ├── BlurLinearLayout.kt │ │ ├── SystemBlurController.kt │ │ ├── ViewExtensions.kt │ │ └── model/ │ │ └── CornerRadius.kt │ └── res/ │ ├── color/ │ │ ├── ic_small_window_color.xml │ │ ├── ic_small_window_color2.xml │ │ ├── ic_small_window_color3.xml │ │ ├── ic_small_window_color4.xml │ │ ├── ic_small_window_color5.xml │ │ └── visual_check_text_color.xml │ ├── drawable/ │ │ ├── baseline_wb_sunny_24.xml │ │ ├── bubble_bar_pop_bg.xml │ │ ├── ic_android_settings.xml │ │ ├── ic_arrow_edit.xml │ │ ├── ic_ationbar_back.xml │ │ ├── ic_audio_system.xml │ │ ├── ic_cemiuiler_settings_v130.xml │ │ ├── ic_cemiuiler_settings_v140.xml │ │ ├── ic_control_center_5g_toggle_off.xml │ │ ├── ic_control_center_5g_toggle_on.xml │ │ ├── ic_control_center_gms_toggle_off.xml │ │ ├── ic_control_center_gms_toggle_on.xml │ │ ├── ic_default_icon.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ic_miui_volume_notification.xml │ │ ├── ic_miui_volume_notification_mute.xml │ │ ├── ic_packageinstaller_background_dark.xml │ │ ├── ic_packageinstaller_background_light.xml │ │ ├── ic_qs_tile_bg_disabled.xml │ │ ├── ic_qs_tile_bg_enabled.xml │ │ ├── ic_qs_tile_bg_warning.xml │ │ ├── ic_reboot_small.xml │ │ ├── ic_settings.xml │ │ ├── ic_small_window.xml │ │ ├── ic_system_framework_new.xml │ │ ├── ic_system_ui_new.xml │ │ ├── ic_various.xml │ │ ├── shutdown_progress.xml │ │ ├── statusbar_signal_1_0.xml │ │ ├── statusbar_signal_1_0_dark.xml │ │ ├── statusbar_signal_1_0_dark_thick.xml │ │ ├── statusbar_signal_1_0_thick.xml │ │ ├── statusbar_signal_1_0_tint.xml │ │ ├── statusbar_signal_1_0_tint_thick.xml │ │ ├── statusbar_signal_1_1.xml │ │ ├── statusbar_signal_1_1_dark.xml │ │ ├── statusbar_signal_1_1_dark_thick.xml │ │ ├── statusbar_signal_1_1_thick.xml │ │ ├── statusbar_signal_1_1_tint.xml │ │ ├── statusbar_signal_1_1_tint_thick.xml │ │ ├── statusbar_signal_1_2.xml │ │ ├── statusbar_signal_1_2_dark.xml │ │ ├── statusbar_signal_1_2_dark_thick.xml │ │ ├── statusbar_signal_1_2_thick.xml │ │ ├── statusbar_signal_1_2_tint.xml │ │ ├── statusbar_signal_1_2_tint_thick.xml │ │ ├── statusbar_signal_1_3.xml │ │ ├── statusbar_signal_1_3_dark.xml │ │ ├── statusbar_signal_1_3_dark_thick.xml │ │ ├── statusbar_signal_1_3_thick.xml │ │ ├── statusbar_signal_1_3_tint.xml │ │ ├── statusbar_signal_1_3_tint_thick.xml │ │ ├── statusbar_signal_1_4.xml │ │ ├── statusbar_signal_1_4_dark.xml │ │ ├── statusbar_signal_1_4_dark_thick.xml │ │ ├── statusbar_signal_1_4_thick.xml │ │ ├── statusbar_signal_1_4_tint.xml │ │ ├── statusbar_signal_1_4_tint_thick.xml │ │ ├── statusbar_signal_1_5.xml │ │ ├── statusbar_signal_1_5_dark.xml │ │ ├── statusbar_signal_1_5_dark_thick.xml │ │ ├── statusbar_signal_1_5_thick.xml │ │ ├── statusbar_signal_1_5_tint.xml │ │ ├── statusbar_signal_1_5_tint_thick.xml │ │ ├── statusbar_signal_2_0.xml │ │ ├── statusbar_signal_2_0_dark.xml │ │ ├── statusbar_signal_2_0_dark_thick.xml │ │ ├── statusbar_signal_2_0_thick.xml │ │ ├── statusbar_signal_2_0_tint.xml │ │ ├── statusbar_signal_2_0_tint_thick.xml │ │ ├── statusbar_signal_2_1.xml │ │ ├── statusbar_signal_2_1_dark.xml │ │ ├── statusbar_signal_2_1_dark_thick.xml │ │ ├── statusbar_signal_2_1_thick.xml │ │ ├── statusbar_signal_2_1_tint.xml │ │ ├── statusbar_signal_2_1_tint_thick.xml │ │ ├── statusbar_signal_2_2.xml │ │ ├── statusbar_signal_2_2_dark.xml │ │ ├── statusbar_signal_2_2_dark_thick.xml │ │ ├── statusbar_signal_2_2_thick.xml │ │ ├── statusbar_signal_2_2_tint.xml │ │ ├── statusbar_signal_2_2_tint_thick.xml │ │ ├── statusbar_signal_2_3.xml │ │ ├── statusbar_signal_2_3_dark.xml │ │ ├── statusbar_signal_2_3_dark_thick.xml │ │ ├── statusbar_signal_2_3_thick.xml │ │ ├── statusbar_signal_2_3_tint.xml │ │ ├── statusbar_signal_2_3_tint_thick.xml │ │ ├── statusbar_signal_2_4.xml │ │ ├── statusbar_signal_2_4_dark.xml │ │ ├── statusbar_signal_2_4_dark_thick.xml │ │ ├── statusbar_signal_2_4_thick.xml │ │ ├── statusbar_signal_2_4_tint.xml │ │ ├── statusbar_signal_2_4_tint_thick.xml │ │ ├── statusbar_signal_2_5.xml │ │ ├── statusbar_signal_2_5_dark.xml │ │ ├── statusbar_signal_2_5_dark_thick.xml │ │ ├── statusbar_signal_2_5_thick.xml │ │ ├── statusbar_signal_2_5_tint.xml │ │ └── statusbar_signal_2_5_tint_thick.xml │ ├── drawable-v31/ │ │ └── ic_launcher_foreground.xml │ ├── layout/ │ │ ├── activity_about.xml │ │ ├── activity_custom_hook.xml │ │ ├── activity_custom_hook_config.xml │ │ ├── activity_location.xml │ │ ├── fragment_app_picker.xml │ │ ├── fragment_common_padded.xml │ │ ├── frame_content.xml │ │ ├── item_app_list.xml │ │ ├── item_location.xml │ │ ├── item_mutiplechoice.xml │ │ ├── item_search_result.xml │ │ ├── location_edit_dialog.xml │ │ ├── preference_custom_blur_dark_mode.xml │ │ ├── preference_custom_blur_light_mode.xml │ │ ├── preference_dialog_edittext.xml │ │ ├── preference_divider.xml │ │ ├── preference_header.xml │ │ ├── preference_round_layout.xml │ │ ├── preference_seekbar_no_padding.xml │ │ ├── preference_text.xml │ │ ├── settings_main.xml │ │ ├── statusbar_text_icon.xml │ │ └── view_mutiplechoice.xml │ ├── menu/ │ │ ├── menu_location.xml │ │ ├── menu_location_simulation.xml │ │ ├── menu_main.xml │ │ └── menu_system_framework_other.xml │ ├── mipmap-anydpi-v26/ │ │ └── ic_launcher.xml │ ├── resources.properties │ ├── values/ │ │ ├── arrays.xml │ │ ├── attrs.xml │ │ ├── bools.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── integer.xml │ │ ├── strings.xml │ │ └── themes.xml │ ├── values-ja-rJP/ │ │ └── strings.xml │ ├── values-night/ │ │ └── themes.xml │ ├── values-night-v31/ │ │ └── colors.xml │ ├── values-pt-rBR/ │ │ └── strings.xml │ ├── values-ru-rRU/ │ │ └── strings.xml │ ├── values-tr-rTR/ │ │ └── strings.xml │ ├── values-v31/ │ │ └── colors.xml │ ├── values-vi-rVN/ │ │ └── strings.xml │ ├── values-zh-rCN/ │ │ └── strings.xml │ ├── values-zh-rHK/ │ │ └── strings.xml │ ├── values-zh-rTW/ │ │ └── strings.xml │ └── xml/ │ ├── aiasst.xml │ ├── aod.xml │ ├── backup_rules.xml │ ├── barrage.xml │ ├── browser.xml │ ├── camera.xml │ ├── clock.xml │ ├── content_extension.xml │ ├── creation.xml │ ├── custom_background.xml │ ├── data_extraction_rules.xml │ ├── downloads.xml │ ├── fileexplorer.xml │ ├── framework.xml │ ├── framework_display.xml │ ├── framework_freeform.xml │ ├── framework_other.xml │ ├── framework_phone.xml │ ├── framework_volume.xml │ ├── gallery.xml │ ├── guard_provider.xml │ ├── home.xml │ ├── home_dock.xml │ ├── home_drawer.xml │ ├── home_folder.xml │ ├── home_gesture.xml │ ├── home_layout.xml │ ├── home_multi_action.xml │ ├── home_other.xml │ ├── home_recent.xml │ ├── home_title.xml │ ├── home_title_anim.xml │ ├── home_title_anim_1.xml │ ├── home_title_anim_2.xml │ ├── home_title_anim_3.xml │ ├── home_title_anim_4.xml │ ├── home_title_anim_5.xml │ ├── home_title_anim_6.xml │ ├── home_title_anim_7.xml │ ├── home_title_anim_8.xml │ ├── home_widget.xml │ ├── incallui.xml │ ├── joyose.xml │ ├── lbe_security.xml │ ├── market.xml │ ├── mediaeditor.xml │ ├── mi_settings.xml │ ├── milink.xml │ ├── mirror.xml │ ├── mishare.xml │ ├── miwallpaper.xml │ ├── mms.xml │ ├── mtb.xml │ ├── music.xml │ ├── networkboost.xml │ ├── nfc.xml │ ├── package_installer.xml │ ├── personal_assistant.xml │ ├── phone.xml │ ├── powerkeeper.xml │ ├── prefs_about.xml │ ├── prefs_about_contributor.xml │ ├── prefs_about_use.xml │ ├── prefs_main.xml │ ├── prefs_settings.xml │ ├── scanner.xml │ ├── screenrecorder.xml │ ├── screenshot.xml │ ├── security_center.xml │ ├── settings_safe_mode.xml │ ├── system_settings.xml │ ├── system_ui.xml │ ├── system_ui_control_center.xml │ ├── system_ui_lock_screen.xml │ ├── system_ui_navigation.xml │ ├── system_ui_other.xml │ ├── system_ui_status_bar.xml │ ├── system_ui_status_bar_battery_indicator.xml │ ├── system_ui_status_bar_battery_styles.xml │ ├── system_ui_status_bar_clock_indicator.xml │ ├── system_ui_status_bar_doubleline_network.xml │ ├── system_ui_status_bar_hardware_detail_indicator.xml │ ├── system_ui_status_bar_icon_manage.xml │ ├── system_ui_status_bar_mobile_network_type.xml │ ├── system_ui_status_bar_network_speed_indicator.xml │ ├── theme_manager.xml │ ├── tsmclient.xml │ ├── updater.xml │ ├── various.xml │ ├── various_aosp.xml │ ├── various_dialog.xml │ ├── various_location_simulation.xml │ ├── various_mipad.xml │ └── weather.xml ├── build.gradle ├── config.gradle ├── crowdin.yml ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.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 │ └── miui/ │ ├── app/ │ │ └── MiuiFreeFormManager.java │ └── drm/ │ ├── DrmManager.kt │ └── ThemeReceiver.kt ├── settings.gradle └── signing.properties.example ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ root = true [*] charset = utf-8 end_of_line = lf indent_size = 4 indent_style = space insert_final_newline = true trim_trailing_whitespace = true [*.xml] insert_final_newline = false [*.yml] indent_size = 2 ================================================ FILE: .gitattributes ================================================ # Auto detect text files and perform LF normalization * text=auto eol=lf ================================================ FILE: .github/ISSUE_TEMPLATE/BUG-REPORT.yml ================================================ name: "🐛 Bug" description: 问题报告. title: "🐛 [BUG] <问题标题>" labels: [ "bug" ] body: - type: textarea id: description attributes: label: "问题描述" description: 请输入简洁且明确的问题描述。 placeholder: ...的...功能出现...异常 validations: required: true - type: textarea id: log attributes: label: "模块日志" description: LSPosed管理器 - 日志 或 软件崩溃日志 placeholder: ... validations: required: true - type: textarea id: repord attributes: label: "复现步骤" description: 输入简明的问题复现步骤。 value: | 1. 前往 '...' 2. 点击 '....' .... 出现问题 render: bash validations: required: false - type: textarea id: screenshot attributes: label: "问题截图" description: 添加问题截图以便我们快速定位. value: | ![图片注释](图片链接) validations: required: false - type: input id: device attributes: label: "机型" description: 填写你的机型,可填型号. placeholder: Xiaomi validations: required: true - type: dropdown id: miui_version attributes: label: "MIUI 版本" description: 您当前正在使用的 MIUI 版本 multiple: true options: - MIUI12 / MIUI12.5 - MIUI13 - MIUI14 - MIUI15 - 其它 validations: required: true - type: dropdown id: android_version attributes: label: "Android 版本" description: 您当前正在使用的 Android 版本 multiple: true options: - Android 11 - Android 12 - Android 13 - Android 14 validations: required: true - type: input id: cemiuiler_version attributes: label: "Cemiuiler 版本" description: 填写您的 Cemiuiler 版本. placeholder: x.y.z-YYYYMMDD validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml ================================================ name: "💡 需求" description: 新功能需求 title: "💡 [需求] <标题>" labels: [ "enhancement" ] body: - type: textarea id: requirement attributes: label: "需求内容" description: "简单说明你的需求" placeholder: 请添加... validations: required: true - type: textarea id: refs attributes: label: "实现思路&截图" description: 如果可能,请提供实现思路或者相关图片 placeholder: "![图片描述](图片链接)" validations: required: false - type: textarea id: basic_example attributes: label: "简单例子" description: 说明该功能的基本示例 placeholder: 为...添加...以便... validations: required: true ================================================ FILE: .github/ISSUE_TEMPLATE/MIGRATION-REQUEST.yml ================================================ name: "🔌 移植" description: 新功能需求 title: "🔌 [移植] <标题>" labels: [ "enhancement" ] body: - type: input id: repo attributes: label: "仓库地址" description: "提供仓库地址以便我们更快地工作" placeholder: "https://github.com/" validations: required: false - type: textarea id: requirement attributes: label: "移植内容" description: "简单说明需要移植的内容" placeholder: 移植...软件的...功能 validations: required: true - type: textarea id: feature_desc attributes: label: "相关描述&截图" description: 如果可能,请提供相关功能描述及图片 placeholder: "![图片描述](图片链接)" validations: required: false ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false ================================================ FILE: .github/dependabot.yml ================================================ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "gradle" directory: "/" schedule: interval: "daily" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" ================================================ FILE: .github/workflows/android.yml ================================================ name: Android CI on: push: branches: [ "main" ] pull_request: branches: [ "main" ] paths-ignore: - ".github/**" - "!.github/workflows/**" - ".idea/" - "doc/*" - "*.md" - ".github/workflows/crowdin.yml" - "crowdin.yml" workflow_dispatch: jobs: build: runs-on: ubuntu-latest name: Build App steps: - name: Checkout Git Repository uses: actions/checkout@v4 with: fetch-depth: 0 submodules: true - name: Set up JDK 20 uses: actions/setup-java@v3 with: java-version: '20' distribution: 'temurin' cache: gradle - name: Create Sign File if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' run: | touch signing.properties echo storePassword=${{ secrets.KEY_STORE_PASSWORD }} >> signing.properties echo keyAlias=${{ secrets.ALIAS }} >> signing.properties echo keyPassword='${{ secrets.KEY_STORE_PASSWORD }}' >> signing.properties echo storeFile=key.jks >> signing.properties echo ${{ secrets.SIGNING_KEY }} | base64 --decode > key.jks - name: Build with Gradle shell: bash run: ./gradlew assembleCanary - name: Find APKs run: | echo "APK_FILE_CANARY=$(find app/build/outputs/apk/canary -name '*.apk')" >> $GITHUB_ENV - name: Show APKs SHA256 if: success() run: | echo "### Build Success" >> $GITHUB_STEP_SUMMARY echo "|Artifact|SHA256|" >> $GITHUB_STEP_SUMMARY echo "|:--------:|:----------|" >> $GITHUB_STEP_SUMMARY canary=($(sha256sum '${{ env.APK_FILE_CANARY }}')) echo "|Canary|$canary" >> $GITHUB_STEP_SUMMARY - name: Upload Canary APK if: contains(github.event.head_commit.message, '[upload]') == true uses: actions/upload-artifact@v3 with: name: Cemiuiler Canary path: ${{ env.APK_FILE_CANARY }} - name: Post to Beta Channel & Canary Group if: ${{ github.event_name != 'pull_request' && github.ref == 'refs/heads/main' && github.ref_type != 'tag' && contains(github.event.head_commit.message, '[skip post]') == false && contains(github.event.head_commit.message, 's#') == false }} shell: bash env: GROUP_ID: ${{ secrets.CANARY_GROUP_ID }} GROUP_ID_TEMPORARY: ${{ secrets.GROUP_TEMPORARY_ID }} CHANNEL_ID: ${{ secrets.CHANNEL_ID }} MESSAGE_THREAD_ID: ${{ secrets.MESSAGE_THREAD_ID }} BOT_TOKEN: ${{ secrets.BOT_TOKEN }} CANARY: ${{ env.APK_FILE_CANARY }} run: | mkdir -p ${{ github.workspace }}/git_clone git clone ${{ github.event.repository.url }} ${{ github.workspace }}/git_clone -b ${{ github.ref_name }} cd ${{ github.workspace }}/git_clone { echo -e 'Github CI\n'; git log ${{ github.event.before }}..${{ github.event.after }} --pretty=format:"%h %s"; } > ${{ github.workspace }}/git_log ESCAPED="$(cat ${{ github.workspace }}/git_log | gawk '{gsub(/[_*[\]()~`>#+=\|{}.!-]/,"\\\\\\\\&")}1' | sed -e 's|"|\\"|g' -e 's|^[0-9a-z]\+|__&__|' | hexdump -v -e '/1 "%02X"' | sed 's/\(..\)/%\1/g')" cd ${{ github.workspace }} curl -v "https://api.telegram.org/bot${BOT_TOKEN}/sendMediaGroup?chat_id=${GROUP_ID}&message_thread_id=${MESSAGE_THREAD_ID}&media=%5B%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Fcanary%22%2C%22parse_mode%22%3A%22MarkdownV2%22%2C%22caption%22%3A%22${ESCAPED}%22%7D%5D" -F canary="@${CANARY}" 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%2Fcanary%22%2C%22parse_mode%22%3A%22MarkdownV2%22%2C%22caption%22%3A%22${ESCAPED}%22%7D%5D" -F canary="@${CANARY}" ================================================ FILE: .github/workflows/androidu.yml ================================================ name: Android U Action on: push: branches: [ "Android-U" ] pull_request: branches: [ "Android-U" ] paths-ignore: - ".github/**" - "!.github/workflows/**" - ".idea/" - "doc/*" - "*.md" - ".github/workflows/crowdin.yml" - "crowdin.yml" workflow_dispatch: jobs: build: runs-on: ubuntu-latest name: Build App steps: - name: Checkout Git Repository uses: actions/checkout@v4 with: fetch-depth: 0 submodules: true - name: Set up JDK 20 uses: actions/setup-java@v3 with: java-version: '20' distribution: 'temurin' cache: gradle - name: Create Sign File run: | touch signing.properties echo storePassword=${{ secrets.KEY_STORE_PASSWORD }} >> signing.properties echo keyAlias=${{ secrets.ALIAS }} >> signing.properties echo keyPassword='${{ secrets.KEY_STORE_PASSWORD }}' >> signing.properties echo storeFile=key.jks >> signing.properties echo ${{ secrets.SIGNING_KEY }} | base64 --decode > key.jks - name: Build with Gradle if: contains(github.event.head_commit.message, '[skip]') == false shell: bash run: ./gradlew assembleCanary - name: Find APKs if: contains(github.event.head_commit.message, '[skip]') == false run: | echo "APK_FILE_CANARY=$(find app/build/outputs/apk/canary -name '*.apk')" >> $GITHUB_ENV - name: Show APKs SHA256 if: success() && contains(github.event.head_commit.message, '[skip]') == false run: | echo "### Build Success" >> $GITHUB_STEP_SUMMARY echo "|Artifact|SHA256|" >> $GITHUB_STEP_SUMMARY echo "|:--------:|:----------|" >> $GITHUB_STEP_SUMMARY canary=($(sha256sum '${{ env.APK_FILE_CANARY }}')) echo "|Canary|$canary" >> $GITHUB_STEP_SUMMARY - name: Upload Canary APK if: contains(github.event.head_commit.message, '[upload]') == true uses: actions/upload-artifact@v3 with: name: Cemiuiler Canary path: ${{ env.APK_FILE_CANARY }} - name: Post to Android 14 Debug Group if: contains(github.event.head_commit.message, '[skip]') == false shell: bash env: GROUP_ID: ${{ secrets.DEBUG_GROUP_ID }} GROUP_ID_TEMPORARY: ${{ secrets.GROUP_TEMPORARY_ID }} BOT_TOKEN: ${{ secrets.BOT_TOKEN }} CANARY: ${{ env.APK_FILE_CANARY }} run: | mkdir -p ${{ github.workspace }}/git_clone git clone ${{ github.event.repository.url }} ${{ github.workspace }}/git_clone -b ${{ github.ref_name }} cd ${{ github.workspace }}/git_clone { echo -e 'Github CI\n'; git log ${{ github.event.before }}..${{ github.event.after }} --pretty=format:"%h %s"; } > ${{ github.workspace }}/git_log ESCAPED="$(cat ${{ github.workspace }}/git_log | gawk '{gsub(/[_*[\]()~`>#+=\|{}.!-]/,"\\\\\\\\&")}1' | sed -e 's|"|\\"|g' -e 's|^[0-9a-z]\+|__&__|' | hexdump -v -e '/1 "%02X"' | sed 's/\(..\)/%\1/g')" cd ${{ github.workspace }} curl -v "https://api.telegram.org/bot${BOT_TOKEN}/sendMediaGroup?chat_id=${GROUP_ID}&media=%5B%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Fcanary%22%2C%22parse_mode%22%3A%22MarkdownV2%22%2C%22caption%22%3A%22${ESCAPED}%22%7D%5D" -F canary="@${CANARY}" ================================================ FILE: .github/workflows/crowdin.yml ================================================ name: Crowdin Action on: workflow_dispatch: push: branches: [ main ] paths: - app/src/main/res/values/strings.xml schedule: - cron: '0 0 * * *' permissions: contents: write pull-requests: write jobs: synchronize-with-crowdin: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Crowdin Action uses: crowdin/github-action@master with: # Upload and download translation settings upload_sources: true upload_translations: true download_translations: true # Pull request settings create_pull_request: true localization_branch_name: crowdin_branch pull_request_labels: 'enhancement, documentation' # Global settings config: 'crowdin.yml' crowdin_branch_name: main env: GITHUB_TOKEN: ${{ secrets.GIT_TOKEN }} CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} CROWDIN_API_TOKEN: ${{ secrets.CROWDIN_API_TOKEN }} ================================================ FILE: .gitignore ================================================ *.iml .gradle /local.properties .idea .DS_Store /build /captures .externalNativeBuild .cxx local.properties /app/release /app/beta /app/canary /app/debug ================================================ FILE: LICENSE ================================================ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Remote Network Interaction; Use with the GNU General Public License. Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . ================================================ FILE: README.md ================================================
# Cemiuiler ### Make MIUI Great Again! 简体中文  |  [English](/README_en-US.md) |  [Português (Brasil)](/README_pt-BR.md)
## 支持的版本 Android 11 ~ 13 的 MIUI 12.5 ~ 14 > 不支持 修改较多的第三方 MIUI Rom、修改较多的系统软件,以及部分国外 MIUI Rom, > > 目前 Cemiuiler 是基于 Android 13 的 MIUI 14 的手机端设备进行适配,覆盖不是很完整,需要不断测试和改进, > > 本项目已迁移,请前往[新项目](https://github.com/saraSakuHj/HyperCeiler) ## 作用域包含的应用
点击展开折叠的内容 | 应用名 | 包名 | | :---- | :---- | | 系统框架 | system | | 系统界面 | com.android.systemui | | 系统桌面 | com.miui.home | | 系统更新 | com.android.updater | | Joyose | com.xiaomi.joyose | | 小米设置 | com.xiaomi.misettings | | 手机管家 | com.miui.securitycenter | | 笔记 | com.miui.notes | | 壁纸 | com.miui.miwallpaper | | 传送门 | com.miui.contentextension | | 弹幕通知 | com.xiaomi.barrage | | 百度输入法小米版 | com.baidu.input_mi | | 电话 | com.android.incallui | | 电话服务 | com.android.phone | | 电量与性能 | com.miui.powerkeeper | | 短信 | com.android.mms | | 截屏 | com.miui.screenshot | | 垃圾清理 | com.miui.cleanmaster | | 浏览器 | com.android.browser | | 鲁班(MTB) | com.xiaomi.mtb | | 屏幕录制 | com.miui.screenrecorder | | 权限管理服务 | com.lbe.security.miui | | 设置 | com.android.settings | 搜狗输入法小米版 | com.sohu.inputmethod.sogou.xiaomi | | 天气 | com.miui.weather2 | | 投屏 | com.milink.service | | 外部存储设备 | com.android.externalstorage | | 万象息屏 | com.miui.aod | | 文件管理 | com.android.fileexplorer | | 系统服务组件 | com.miui.securityadd | | 下载管理 | com.android.providers.downloads.ui | | 下载管理程序 | com.android.providers.downloads | | 相册 | com.miui.gallery | | 小米创作 | com.miui.creation | | 小米互传 | com.miui.mishare.connectivity | | 小米相册 - 编辑 | com.miui.mediaeditor | | 小米云服务 | com.miui.cloudservice | | 小米智能卡 | com.miui.tsmclient | | 讯飞输入法小米版 | com.iflytek.inputmethod.miui | | 应用包管理组件 | com.miui.packageinstaller | | 应用商店 | com.xiaomi.market | | 智能助理 | com.miui.personalassistant | | 主题壁纸 | com.android.thememanager | | com.miui.rom | com.miui.rom | | MIUI 安全组件 | com.miui.guardprovider | | 时钟 | com.android.deskclock | | 相机 | com.android.camera | | 小爱翻译 | com.xiaomi.aiasst.vision | | 小爱建议 | com.xiaomi.aireco | | 小爱视觉 | com.xiaomi.scanner | | 小爱同学 | com.miui.voiceassist | | 音乐 | com.miui.player | | MIUI+ Beta 版 | com.xiaomi.mirror | | com.xiaomi.NetworkBoost | com.xiaomi.NetworkBoost | | NFC 服务 | com.android.nfc |
> 与 LSPosed 中推荐的作用域相同 ## 交流 & 反馈群组 加入我们所创建的群组以反馈问题或是了解最新情况。 [![badge_qgroup]][qgroup_url] [![badge_qguild]][qguild_url] [![badge_telegram]][telegram_url] ## 为 Cemiuiler 贡献翻译 [![Crowdin](https://badges.crowdin.net/cemiuiler/localized.svg)](https://crowdin.com/project/cemiuiler) 您可以在[这里](https://crwd.in/cemiuiler)为 Cemiuiler 项目贡献翻译。 ## 感谢 > Cemiuiler 使用了以下开源项目的部分或全部内容,感谢这些项目的开发者提供的大力支持(排名顺序不分先后)。 - [「Accompanist」 by Android Open Source Project, Google Inc.](https://google.github.io/accompanist) - [「Android」 by Android Open Source Project, Google Inc.](https://source.android.google.cn/license) - [「AndroidHiddenApiBypass」 by LSPosed](https://github.com/LSPosed/AndroidHiddenApiBypass) - [「AndroidX」 by Android Open Source Project, Google Inc.](https://github.com/androidx/androidx) - [「AntiAntiDefraud」 by MinaMichita](https://github.com/MinaMichita/AntiAntiDefraud) - [「Auto NFC」 by GSWXXN](https://github.com/GSWXXN/AutoNFC) - [「BypassSignCheck」 by Weverses](https://github.com/Weverses/BypassSignCheck) - [「CorePatch」 by LSPosed](https://github.com/LSPosed/CorePatch) - [「CustoMIUIzer」 by MonwF](https://github.com/MonwF/customiuizer) - [「CustoMIUIzerMod」 by liyafe1997](https://github.com/liyafe1997/CustoMIUIzerMod) - [「DexKit」 by LuckyPray](https://github.com/LuckyPray/DexKit) - [「Disable app link verify」 by tehcneko](https://github.com/Xposed-Modules-Repo/io.github.tehcneko.applinkverify) - [「DisableFlagSecure」 by LSPosed](https://github.com/LSPosed/DisableFlagSecure) - [「DisableLogRequest」 by QueallyTech](https://github.com/QueallyTech/DisableLogRequest) - [「EzXHelper」 by KyuubiRan](https://github.com/KyuubiRan/EzXHelper) - [「FixMiuiMediaControlPanel」 by qqlittleice](https://github.com/qqlittleice/FixMiuiMediaControlPanel) - [「FuckNFC」 by xiaowine](https://github.com/xiaowine/FuckNFC) - [「Gson」 by Android Open Source Project, Google Inc.](https://github.com/google/gson) - [「HideMiuiClipboardDialog」 by zerorooot](https://github.com/zerorooot/HideMiuiClipboardDialog) - [「Kotlin」 by JetBrains](https://github.com/JetBrains/kotlin) - [「MaxFreeForm」 by YifePlayte](https://github.com/YifePlayte/MaxFreeForm) - [「Miui Feature」 by MoralNorm](https://github.com/moralnorm/miui_feature) - [「MiuiHomeR」 by qqlittleice](https://github.com/qqlittleice/MiuiHome_R) - [「MIUI IME Unlock」 by RC1844](https://github.com/RC1844/MIUI_IME_Unlock) - [「MIUI QOL」 by chsbuffer](https://github.com/chsbuffer/MIUIQOL) - [「Miui XXL」 by Wine-Network](https://github.com/Wine-Network/Miui_XXL) - [「Miui XXL」 by YuKongA](https://github.com/YuKongA/Miui_XXL) - [「MIUI 通知修复」 by tehcneko](https://github.com/Xposed-Modules-Repo/io.github.tehcneko.miuinotificationfix) - [「ModemPro」 by Weverse](https://github.com/Weverses/ModemPro) - [「NoStorageRestrict」 by DanGLES3](https://github.com/Xposed-Modules-Repo/com.github.dan.nostoragerestrict) - [「Portal Hook」 by Haocen2004](https://github.com/Haocen2004/PortalHook) - [「RemoveMiuiSystemSelfProtection」 by gfbjngjibn](https://github.com/gfbjngjibn/RemoveMiuiSystemSelfProtection) - [「SettingsDontThroughTheList」 by weixiansen574](https://github.com/weixiansen574/settingsdontthroughthelist) - [「StarVoyager」 by hosizoraru](https://github.com/hosizoraru/StarVoyager) - [「WINI」 by ouhoukyo](https://github.com/ouhoukyo/WINI) - [「WOMMO」 by YifePlayte](https://github.com/YifePlayte/WOMMO) - [「Woobox For MIUI」 by hosizoraru](https://github.com/hosizoraru/WooBoxForMIUI) - [「Woobox For MIUI」 by Simplicity-Team](https://github.com/Simplicity-Team/WooBoxForMIUI) - [「Xposed」 by rovo89, Tungstwenty](https://github.com/rovo89/XposedBridge) - [「XposedBridge」 by rovo89](https://github.com/rovo89/XposedBridge) - [「.xlDownload」 by Kr328](https://github.com/Kr328/.xlDownload) [qgroup_url]: https://jq.qq.com/?_wv=1027&k=TedCJq8V [badge_qgroup]: https://img.shields.io/badge/QQ-群组-4DB8FF?style=for-the-badge&logo=tencentqq [qguild_url]: https://pd.qq.com/s/35ooe0ssj [badge_qguild]: https://img.shields.io/badge/QQ-频道-4991D3?style=for-the-badge&logo=tencentqq [telegram_url]: https://t.me/cemiuiler [badge_telegram]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=2CA5E0&label=Telegram&logo=telegram&query=%24.data.totalSubs&url=https%3A%2F%2Fapi.spencerwoo.com%2Fsubstats%2F%3Fsource%3Dtelegram%26queryKey%3Dcemiuiler ================================================ FILE: README_en-US.md ================================================
# Cemiuiler ### Make MIUI Great Again! English  |  [简体中文](/README.md) |  [Português (Brasil)](/README_pt-BR.md)
## Supported versions MIUI 12.5 ~ 14 for Android 11 ~ 13 > Does not support third-party MIUI ROMs with many modifications, system software with many modifications, and some foreign MIUI ROMs > > At present, Cemiuiler is based on Android 13 MIUI 14 mobile phone devices for adaptation, the coverage is not very complete, it needs continuous testing and improvement > > We have tried our best to support Android 11 devices. After the release of version 1.3.130, the mainline branch will no longer support Android 11, but it will still provide maintenance and porting of old version functions. ## Supported Applications
Click to expand collapsed content | App Name | Package Name | | :---- | :---- | | System Framework | system | | System UI | com.android.systemui | | System Launcher | com.miui.home | | Updater | com.android.updater | | Joyose | com.xiaomi.joyose | | Settings | com.xiaomi.misettings | | Security | com.miui.securitycenter | | Notes | com.miui.notes | | Mi Wallpaper | com.miui.miwallpaper | | Taplus | com.miui.contentextension | | Bullet screen notification | com.xiaomi.barrage | | Baidu IME for MIUI | com.baidu.input_mi | | Phone | com.android.incallui | | Phone Services | com.android.phone | | Battery and performance | com.miui.powerkeeper | | Messaging | com.android.mms | | Screenshot | com.miui.screenshot | | Cleaner | com.miui.cleanmaster | | Browser | com.android.browser | | Rueban (MTB) | com.xiaomi.mtb | | Screen Recorder | com.miui.screenrecorder | | Permissions | com.lbe.security.miui | | Settings | com.android.settings | Sogou Keyboard for MIUI | com.sohu.inputmethod.sogou.xiaomi | | Weather | com.miui.weather2 | | Cast | com.milink.service | | External Storage | com.android.externalstorage | | Always-on display | com.miui.aod | | File Manager | com.android.fileexplorer | | System Service Plugin | com.miui.securityadd | | Downloads | com.android.providers.downloads.ui | | Downloads | com.android.providers.downloads | | Gallery | com.miui.gallery | | Mi Canvas | com.miui.creation | | Mi Share | com.miui.mishare.connectivity | | Gallery Editor | com.miui.mediaeditor | | Xiaomi Cloud | com.miui.cloudservice | | Smart Cards | com.miui.tsmclient | | iFlytek IME for MIUI | com.iflytek.inputmethod.miui | | Package Installer | com.miui.packageinstaller | | GetApps | com.xiaomi.market | | App Vault | com.miui.personalassistant | | Themes | com.android.thememanager | | com.miui.rom | com.miui.rom | | MIUI Security Components | com.miui.guardprovider | | Clock | com.android.deskclock | | Camera | com.android.camera | | Mi AI Translate | com.xiaomi.aiasst.vision | | Mi AI Suggestions | com.xiaomi.aireco | | Scanner | com.xiaomi.scanner | | Mi AI | com.miui.voiceassist | | Music | com.miui.player | | MIUI+ Beta | com.xiaomi.mirror | | com.xiaomi.NetworkBoost | com.xiaomi.NetworkBoost |
> Same scope as recommended in LSPosed ## Chat & Feedback Group Join our group to report issues or get the latest updates. [![badge_qgroup]][qgroup_url] [![badge_qguild]][qguild_url] [![badge_telegram]][telegram_url] ## Provide translations for the Cemiuiler project [![Crowdin](https://badges.crowdin.net/cemiuiler/localized.svg)](https://crowdin.com/project/cemiuiler) You can provide translations for the Cemiuiler project [here](https://crwd.in/cemiuiler). ## Thank! > Cemiuiler I have used some or all of the content of the following open source projects. Thank you for the strong support provided by the developers of these projects (in no particular order). - [「Accompanist」 by Android Open Source Project, Google Inc.](https://google.github.io/accompanist) - [「Android」 by Android Open Source Project, Google Inc.](https://source.android.google.cn/license) - [「AndroidHiddenApiBypass」 by LSPosed](https://github.com/LSPosed/AndroidHiddenApiBypass) - [「AndroidX」 by Android Open Source Project, Google Inc.](https://github.com/androidx/androidx) - [「AntiAntiDefraud」 by MinaMichita](https://github.com/MinaMichita/AntiAntiDefraud) - [「Auto NFC」 by GSWXXN](https://github.com/GSWXXN/AutoNFC) - [「BypassSignCheck」 by Weverses](https://github.com/Weverses/BypassSignCheck) - [「CorePatch」 by LSPosed](https://github.com/LSPosed/CorePatch) - [「CustoMIUIzer」 by MonwF](https://github.com/MonwF/customiuizer) - [「CustoMIUIzerMod」 by liyafe1997](https://github.com/liyafe1997/CustoMIUIzerMod) - [「DexKit」 by LuckyPray](https://github.com/LuckyPray/DexKit) - [「Disable app link verify」 by tehcneko](https://github.com/Xposed-Modules-Repo/io.github.tehcneko.applinkverify) - [「DisableFlagSecure」 by LSPosed](https://github.com/LSPosed/DisableFlagSecure) - [「DisableLogRequest」 by QueallyTech](https://github.com/QueallyTech/DisableLogRequest) - [「EzXHelper」 by KyuubiRan](https://github.com/KyuubiRan/EzXHelper) - [「FixMiuiMediaControlPanel」 by qqlittleice](https://github.com/qqlittleice/FixMiuiMediaControlPanel) - [「FuckNFC」 by xiaowine](https://github.com/xiaowine/FuckNFC) - [「Gson」 by Android Open Source Project, Google Inc.](https://github.com/google/gson) - [「HideMiuiClipboardDialog」 by zerorooot](https://github.com/zerorooot/HideMiuiClipboardDialog) - [「Kotlin」 by JetBrains](https://github.com/JetBrains/kotlin) - [「MaxFreeForm」 by YifePlayte](https://github.com/YifePlayte/MaxFreeForm) - [「Miui Feature」 by MoralNorm](https://github.com/moralnorm/miui_feature) - [「MiuiHomeR」 by qqlittleice](https://github.com/qqlittleice/MiuiHome_R) - [「MIUI IME Unlock」 by RC1844](https://github.com/RC1844/MIUI_IME_Unlock) - [「MIUI QOL」 by chsbuffer](https://github.com/chsbuffer/MIUIQOL) - [「Miui XXL」 by Wine-Network](https://github.com/Wine-Network/Miui_XXL) - [「Miui XXL」 by YuKongA](https://github.com/YuKongA/Miui_XXL) - [「MIUI 通知修复」 by tehcneko](https://github.com/Xposed-Modules-Repo/io.github.tehcneko.miuinotificationfix) - [「ModemPro」 by Weverse](https://github.com/Weverses/ModemPro) - [「NoStorageRestrict」 by DanGLES3](https://github.com/Xposed-Modules-Repo/com.github.dan.nostoragerestrict) - [「Portal Hook」 by Haocen2004](https://github.com/Haocen2004/PortalHook) - [「RemoveMiuiSystemSelfProtection」 by gfbjngjibn](https://github.com/gfbjngjibn/RemoveMiuiSystemSelfProtection) - [「SettingsDontThroughTheList」 by weixiansen574](https://github.com/weixiansen574/settingsdontthroughthelist) - [「StarVoyager」 by hosizoraru](https://github.com/hosizoraru/StarVoyager) - [「WINI」 by ouhoukyo](https://github.com/ouhoukyo/WINI) - [「WOMMO」 by YifePlayte](https://github.com/YifePlayte/WOMMO) - [「Woobox For MIUI」 by hosizoraru](https://github.com/hosizoraru/WooBoxForMIUI) - [「Woobox For MIUI」 by Simplicity-Team](https://github.com/Simplicity-Team/WooBoxForMIUI) - [「Xposed」 by rovo89, Tungstwenty](https://github.com/rovo89/XposedBridge) - [「XposedBridge」 by rovo89](https://github.com/rovo89/XposedBridge) - [「.xlDownload」 by Kr328](https://github.com/Kr328/.xlDownload) [qgroup_url]: https://jq.qq.com/?_wv=1027&k=TedCJq8V [badge_qgroup]: https://img.shields.io/badge/QQ-group-4DB8FF?style=for-the-badge&logo=tencentqq [qguild_url]: https://pd.qq.com/s/35ooe0ssj [badge_qguild]: https://img.shields.io/badge/QQ-Channel-4991D3?style=for-the-badge&logo=tencentqq [telegram_url]: https://t.me/cemiuiler [badge_telegram]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=2CA5E0&label=Telegram&logo=telegram&query=%24.data.totalSubs&url=https%3A%2F%2Fapi.spencerwoo.com%2Fsubstats%2F%3Fsource%3Dtelegram%26queryKey%3Dcemiuiler ================================================ FILE: README_pt-BR.md ================================================
# Cemiuiler ### Torne a MIUI ótima novamente! [English](/README_en-US.md)  |  [简体中文](/README.md) |  Português (Brasil)
## Versões suportadas MIUI 12.5 ~ 14 para Android 11 ~ 13 > Não suporta ROM MIUI de terceiros com muitas modificações, software de sistema com muitas modificações e algumas ROM MIUI estrangeiras. > > Atualmente, o Cemiuiler é baseado em dispositivos Android 13 MIUI 14 para adaptação, a cobertura não é muito completa, precisa de testes e melhorias contínuas. > > Tentamos o nosso melhor para oferecer suporte a dispositivos Android 11. Após o lançamento da versão 1.3.130, o branch principal não suportará mais o Android 11, mas ainda fornecerá manutenção e portabilidade de funções de versões antigas. > ## Apps suportados
Clique para ver os apps suportados | Nome do app | Nome do pacote | | :---- | :---- | | Framework do Sistema | system | | Ui do Sistema | com.android.systemui | | Launcher do sistema | com.miui.home | | Atualizações | com.android.updater | | Joyose | com.xiaomi.joyose | | Configurações | com.xiaomi.misettings | | Segurança | com.miui.securitycenter | | Notas | com.miui.notes | | Papéis de Parede Mi | com.miui.miwallpaper | | Taplus | com.miui.contentextension | | Notificação de mensagem em tela | com.xiaomi.barrage | | Baidu IME para MIUI | com.baidu.input_mi | | Ui de chamadas | com.android.incallui | | Serviços do smartphone | com.android.phone | | Bateria e desempenho | com.miui.powerkeeper | | Mensagens | com.android.mms | | Captura de tela | com.miui.screenshot | | Limpeza | com.miui.cleanmaster | | Navegador | com.android.browser | | Rueban (MTB) | com.xiaomi.mtb | | Gravador de tela | com.miui.screenrecorder | | Permissões | com.lbe.security.miui | | Configurações | com.android.settings | Teclado Sogou para MIUI | com.sohu.inputmethod.sogou.xiaomi | | Clima | com.miui.weather2 | | Transmitir | com.milink.service | | Armazenamento externo | com.android.externalstorage | | Tela ambiente | com.miui.aod | | Arquivos | com.android.fileexplorer | | Plugin de serviço de sistema | com.miui.securityadd | | Downloads | com.android.providers.downloads.ui | | Downloads | com.android.providers.downloads | | Galeria | com.miui.gallery | | Mi Canvas | com.miui.creation | | Compartilhamento Mi | com.miui.mishare.connectivity | | Editor da Galeria | com.miui.mediaeditor | | MiCloud | com.miui.cloudservice | | Cartões inteligentes | com.miui.tsmclient | | iFlytek IME para MIUI | com.iflytek.inputmethod.miui | | Instalador de Pacotes | com.miui.packageinstaller | | GetApps | com.xiaomi.market | | Assistente | com.miui.personalassistant | | Temas | com.android.thememanager | | com.miui.rom | com.miui.rom | | Componentes de segurança da MIUI | com.miui.guardprovider | | Relógio | com.android.deskclock | | Câmera | com.android.camera | | Tradutor IA | com.xiaomi.aiasst.vision | | AI Reco | com.xiaomi.aireco | | Scanner | com.xiaomi.scanner | | Mi IA | com.miui.voiceassist | | Músicas | com.miui.player | | MIUI+ | com.xiaomi.mirror | | com.xiaomi.NetworkBoost | com.xiaomi.NetworkBoost | | Serviço NFC | com.android.nfc |
> Todos os escopos acima estão ativos no LSPosed ## Chat e Feedback Junte-se ao nosso grupo para relatar problemas ou obter as atualizações mais recentes. [![badge_qgroup]][qgroup_url] [![badge_qguild]][qguild_url] [![badge_telegram]][telegram_url] ## Tradução [![Crowdin](https://badges.crowdin.net/cemiuiler/localized.svg)](https://crowdin.com/project/cemiuiler) Você pode fornecer traduções para o projeto [aqui](https://crwd.in/cemiuiler). ## Obrigado! > Usei parte ou todo o conteúdo dos seguintes projetos de código aberto. Obrigado pelo forte apoio fornecido pelos desenvolvedores desses projetos (em nenhuma ordem em particular). - [「Accompanist」 por Android Open Source Project, Google Inc.](https://google.github.io/accompanist) - [「Android」 por Android Open Source Project, Google Inc.](https://source.android.google.cn/license) - [「AndroidHiddenApiBypass」 por LSPosed](https://github.com/LSPosed/AndroidHiddenApiBypass) - [「AndroidX」 por Android Open Source Project, Google Inc.](https://github.com/androidx/androidx) - [「AntiAntiDefraud」 por MinaMichita](https://github.com/MinaMichita/AntiAntiDefraud) - [「Auto NFC」 por GSWXXN](https://github.com/GSWXXN/AutoNFC) - [「BypassSignCheck」 por Weverses](https://github.com/Weverses/BypassSignCheck) - [「CorePatch」 por LSPosed](https://github.com/LSPosed/CorePatch) - [「CustoMIUIzer」 por MonwF](https://github.com/MonwF/customiuizer) - [「CustoMIUIzerMod」 por liyafe1997](https://github.com/liyafe1997/CustoMIUIzerMod) - [「DexKit」 por LuckyPray](https://github.com/LuckyPray/DexKit) - [「Disable app link verify」 por tehcneko](https://github.com/Xposed-Modules-Repo/io.github.tehcneko.applinkverify) - [「DisableFlagSecure」 por LSPosed](https://github.com/LSPosed/DisableFlagSecure) - [「DisableLogRequest」 por QueallyTech](https://github.com/QueallyTech/DisableLogRequest) - [「EzXHelper」 por KyuubiRan](https://github.com/KyuubiRan/EzXHelper) - [「FixMiuiMediaControlPanel」 por qqlittleice](https://github.com/qqlittleice/FixMiuiMediaControlPanel) - [「FuckNFC」 por xiaowine](https://github.com/xiaowine/FuckNFC) - [「Gson」 por Android Open Source Project, Google Inc.](https://github.com/google/gson) - [「HideMiuiClipboardDialog」 por zerorooot](https://github.com/zerorooot/HideMiuiClipboardDialog) - [「Kotlin」 por JetBrains](https://github.com/JetBrains/kotlin) - [「MaxFreeForm」 por YifePlayte](https://github.com/YifePlayte/MaxFreeForm) - [「Miui Feature」 por MoralNorm](https://github.com/moralnorm/miui_feature) - [「MiuiHomeR」 por qqlittleice](https://github.com/qqlittleice/MiuiHome_R) - [「MIUI IME Unlock」 por RC1844](https://github.com/RC1844/MIUI_IME_Unlock) - [「MIUI QOL」 por chsbuffer](https://github.com/chsbuffer/MIUIQOL) - [「Miui XXL」 por Wine-Network](https://github.com/Wine-Network/Miui_XXL) - [「Miui XXL」 por YuKongA](https://github.com/YuKongA/Miui_XXL) - [「MIUI 通知修复」 por tehcneko](https://github.com/Xposed-Modules-Repo/io.github.tehcneko.miuinotificationfix) - [「ModemPro」 por Weverse](https://github.com/Weverses/ModemPro) - [「NoStorageRestrict」 por DanGLES3](https://github.com/Xposed-Modules-Repo/com.github.dan.nostoragerestrict) - [「Portal Hook」 por Haocen2004](https://github.com/Haocen2004/PortalHook) - [「RemoveMiuiSystemSelfProtection」 por gfbjngjibn](https://github.com/gfbjngjibn/RemoveMiuiSystemSelfProtection) - [「SettingsDontThroughTheList」 por weixiansen574](https://github.com/weixiansen574/settingsdontthroughthelist) - [「StarVoyager」 por hosizoraru](https://github.com/hosizoraru/StarVoyager) - [「WINI」 por ouhoukyo](https://github.com/ouhoukyo/WINI) - [「WOMMO」 por YifePlayte](https://github.com/YifePlayte/WOMMO) - [「Woobox For MIUI」 por hosizoraru](https://github.com/hosizoraru/WooBoxForMIUI) - [「Woobox For MIUI」 por Simplicity-Team](https://github.com/Simplicity-Team/WooBoxForMIUI) - [「Xposed」 por rovo89, Tungstwenty](https://github.com/rovo89/XposedBridge) - [「XposedBridge」 por rovo89](https://github.com/rovo89/XposedBridge) - [「.xlDownload」 por Kr328](https://github.com/Kr328/.xlDownload) [qgroup_url]: https://jq.qq.com/?_wv=1027&k=TedCJq8V [badge_qgroup]: https://img.shields.io/badge/QQ-Grupo-4DB8FF?style=for-the-badge&logo=tencentqq [qguild_url]: https://pd.qq.com/s/35ooe0ssj [badge_qguild]: https://img.shields.io/badge/QQ-Canal-4991D3?style=for-the-badge&logo=tencentqq [telegram_url]: https://t.me/cemiuiler [badge_telegram]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&color=2CA5E0&label=Telegram&logo=telegram&query=%24.data.totalSubs&url=https%3A%2F%2Fapi.spencerwoo.com%2Fsubstats%2F%3Fsource%3Dtelegram%26queryKey%3Dcemiuiler ================================================ FILE: app/.gitignore ================================================ /build ================================================ FILE: app/build.gradle ================================================ import java.time.LocalDateTime import java.time.format.DateTimeFormatter plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' } static def getGitRevision() { return "git rev-parse --short HEAD".execute().text.trim() } android { compileSdk 34 defaultConfig { namespace 'com.sevtinge.cemiuiler' applicationId namespace minSdk 30 targetSdk 34 versionCode 130 versionName "1.3.130" project.archivesBaseName = "Cemiuiler" ndk { // noinspection ChromeOsAbiSupport abiFilters 'arm64-v8a', 'armeabi-v7a' } applicationVariants.configureEach { variant -> variant.outputs.configureEach { outputFileName = project.archivesBaseName + "_" + versionName + "(" + versionCode + ")_" + variant.buildType.name + ".apk" } } } buildFeatures { buildConfig = true } androidResources { generateLocaleConfig = true } packagingOptions { resources { excludes += "/META-INF/**" excludes += "/kotlin/**" excludes += "/*.txt" excludes += "/*.bin" excludes += "/*.json" } dex { useLegacyPackaging = true } } def properties def propertiesFile = rootProject.file('signing.properties') if (propertiesFile.exists()) { properties = new Properties() properties.load(propertiesFile.newDataInputStream()) } def getString = { String propertyName, String environmentName, String prompt -> return properties?.get(propertyName) ?: System.getenv(environmentName) ?: System.console()?.readLine('\n' + prompt + ': ') } def keyStoreFile = getString('storeFile', 'STORE_FILE', 'Store file')?.with(rootProject.&file) signingConfigs { cemiuiler { if (keyStoreFile != null) { storeFile keyStoreFile storePassword getString('storePassword', 'STORE_PASSWORD', 'Store password') keyAlias getString('keyAlias', 'KEY_ALIAS', 'Key alias') keyPassword getString('keyPassword', 'KEY_PASSWORD', 'Key password') } } } buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', 'proguard-log.pro' versionNameSuffix "_" + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now()) if (keyStoreFile != null) { signingConfig signingConfigs.cemiuiler } } beta { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' versionNameSuffix "_" + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now()) if (keyStoreFile != null) { signingConfig signingConfigs.cemiuiler } } canary { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' versionNameSuffix "_" + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now()) + "_" + getGitRevision() if (keyStoreFile != null) { signingConfig signingConfigs.cemiuiler } } debug { versionNameSuffix "_" + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now()) + "_" + getGitRevision() if (keyStoreFile != null) { signingConfig signingConfigs.cemiuiler } } } compileOptions { sourceCompatibility JavaVersion.VERSION_19 targetCompatibility JavaVersion.VERSION_19 } kotlinOptions { jvmTarget = JavaVersion.VERSION_19.toString() } } dependencies { compileOnly(project(":hidden-api")) compileOnly files('libs/miui.jar') compileOnly files("libs/miui-framework.jar") compileOnly(roots.XposedApi) implementation 'org.luckypray:dexkit:2.0.0-rc7' // implementation 'org.luckypray:DexKit:1.1.8' implementation 'io.github.biezhi:TinyPinyin:2.0.3.RELEASE' implementation 'com.github.kyuubiran:EzXHelper:2.0.8' implementation "com.google.accompanist:accompanist-systemuicontroller:0.32.0" implementation "org.lsposed.hiddenapibypass:hiddenapibypass:4.3" implementation "com.google.code.gson:gson:2.10.1" implementation 'commons-codec:commons-codec:1.16.0' implementation roots.AndroidXCore implementation roots.AndroidXCollection implementation roots.AndroidXRecyclerview implementation roots.AndroidXFragment implementation roots.AndroidXLifecycle implementation roots.AndroidXVectorDrawable implementation roots.AndroidXVectorDrawableAnimated implementation roots.AndroidXCustomView implementation roots.AndroidXCustomViewPoolingContainer implementation roots.AndroidXConstraintLayout implementation files(roots.animation) implementation files(roots.appcompat) implementation files(roots.core) implementation files(roots.haptic) implementation files(roots.preference) implementation files(roots.smooth) implementation files(roots.springback) implementation files("libs/hyperceiler_expansion_packs-debug.aar") } ================================================ FILE: app/dict.txt ================================================ 0000O000000o 000O00000Oo 000O00000o0 000O00000o 000O00000oO 000O00000oo 000O0000O0o 000O0000OOo 000O0000Oo0 000O0000Oo 000O0000OoO 00O0000Ooo 00O0000o00 00O0000o0 00O0000o0O 00O0000o0o 00O0000o 00O0000oO0 00O0000oO 00O0000oOO 000O0000oOo 00O0000oo0 00O0000oo 00O0000ooO 00O0000ooo 00O00oOooO 00O00oOooo 00O000O00o 00O000O0OO 00O000O0Oo 000O00oOoOo 00O000O0o0 00O000O0o 00O000O0oO 00O000O0oo 00O000OO00 00O000OO0o 00O000OO 00O000OOOo 00O000OOo0 000O000OOo 00O000OOoO 00O000OOoo 00O000Oo00 00O000Oo0 00O000Oo0O 00O000Oo0o 00O000OoO0 00O00O0Oo 00O000OoO 000O000OoOO 00O000OoOo 00O000Ooo0 00O000Ooo 00O000OooO 00O000Oooo 00O000o000 00O000o00 00O000o00O 00O000o00o 000O000o0 00O000o0O0 00O000o0O 00O000o0OO 00O000o0Oo 00O000o0o0 00O000o0o 00O000o0oo 00O000o 00O000oO00 000O000oO0 00O000oO0O 00O000oO0o 00O000oO 00O000oOO0 00O000oOO 00O000oOOO 00O000oOOo 00O000oOo0 00O000oOo 000O000oOoO 00O000oOoo 00O000oo0 00O000oo0O 00O000oo0o 00O000oo 00O000ooO0 00O000ooO 00O000ooOO 00O000ooOo 000O000ooo0 00O000ooo 00O000oooO 00O000oooo 00oooOoO 00O00oOOoo 00O00O000o 00O00O00Oo 00O00O00o0 00O00O00o 000O00O00oO 00O00O00oo 00O00O0O0o 00O00O0OO 00O00O0OOo 00O00O0Oo0 00O00O0OoO 00O00O0Ooo 00O00O0o00 00O00O0o0 00O00O0o0O 0O00O0o0o 0O00O0o 0O00O0oO0 0O00O0oOO 0O00O0oOo 0O00O0oo0 0O00O0oo 0O00O0ooO 0O00O0ooo 00O00OO0O 0O00OO0o 0O00OOOo 0O00OOo0 0O00OOo 0O00OOoO 0O00OOoo 0O00Oo00 0O00Oo00o 0O00Oo0 00O00Oo0OO 0O00Oo0Oo 0O00Oo0o0 0O00Oo0o 0O00Oo0oO 0O00OooOO 0O00Oo0oo 0O00Oo 0O00OoO0 0O00OoO0o 00O00OoO0O 0O00Ooo 0O00OoO 0O00OoOO0 0O00OoOO 0O00OoOo0 0O00OoOo 0O00OoOoO 0O00OoOoo 0O00Ooo00 00O00Ooo0 0O00Ooo0O 0O00Ooo0o 0O00OooO0 0O00OooO 0O00OooOo 0O00Oooo0 0O00Oooo 0O00Ooooo 0O00OoooO 00O00o0000 0O00o000 0O00o000O 0O00o000o 0O00o00 0O00o00O0 0O00o00O 0O00o00OO 0O00o00Oo 0O00o00o0 00O00o00o 0O00o00oO 0O00o00oo 0O00o0 0O00o0O00 0O00o0O0 0O00oo000 0O00o0O0O 0O00o0O0o 0O00o0O 00O00o0OO0 0O00o0OO 0O00o0OOO 0O00o0OOo 0O00o0Oo0 0O00o0Oo 0O00o0OoO 0O00o0Ooo 0O00o0o00 0O00o0o0 00O00o0o0O 0O00o0o0o 0O00o0o 0O00o0oO0 0O00o0oO 0O00o0oOO 0O00o0oOo 0O00o0oo0 0O00o0oo 0O00o0ooO 000O00o0ooo 00O00o 00O00oO0O0 00O00oO000 00O00oO00 00O00oO00O 00O00oO0OO 00O00oO00o 00O00oO0 00O00oO0O 00O00ooO00 0O00oO0Oo 0O00oO0o0 0O00oO0o 0O00oO0oO 0O00oO0oo 0O00oO 0O00oOO0o 0O00oOO00 0O00oOO0 00O00oOO0O 0O00oOo 0O00oOO 0O00oOOO0 0O00oOOO 0O00oOOOO 0O00oOOOo 0O00oOOo0 0O00oOOo 0O00oOOoO 00O00oOo00 0O00oOo0 0O00oOo0O 0O00oOo0o 0O00oOoO 0O00oOoOO 0O00oOoo0 0O00oOoo 0O00oo00 0O00oo00O 00O00oo00o 0O00oo0 0O00oo0O0 0O00oo0O 0O00oo0OO 0O00oo0Oo 0O00oo0o0 0O00oo0o 0O00oo0oo 0O00oo 00O00ooO0 0O00ooO0O 0O00ooO0o 0O00ooO 0O00ooOo0 0O00ooOO0 0O00ooOO 0O00ooOOO 0O00ooOOo 0O00ooOo 00O00ooOoO 0O00ooOoo 0O00ooo00 0O00ooo0 0O00ooo0o 0O00ooo 0O00oooO0 0O00oooO 0O00oooOO 0O00oooOo 00O00oooo0 0O00oooo 0O00ooooo 0ooooooo 0O0O00oO 0O0O000o 0O0O00OO 0O0O00Oo 0O0O00o0 0O0O00o 00O0O0O0o 0O0O0O 0O0O0OO0 0O0O0OO 0O0O0OOO 0O0O0OOo 0O0O0Oo0 0O0O0OoO 0O0O0Ooo 0O0O0o00 00O0O0o0 0O0O0o0O 0O0O0o0o 0O0O0o 0O0O0oO0 0O0O0oO 0O0O0oOO 0O0O0oOo 0O0O0oo0 0O0O0oo 000O0O0ooO 00O0O0ooo 00O0OoOo 00O0OoOO 00O0OO00O 00O0OO00o 00O0OO0O 00O0Oo0o0 00O0OO0Oo 00O0OO0o0 00O0OO0oO 0O0OO0oo 0O0OOO00 0O0OOoo 0O0OOoO 0O0OOO0 0O0OOO0O 0O0OOO0o 0OO0oO 0O0OOOO 00O0OOOOO 0O0OOOOo 0O0OOOo0 0O0OOOo 0O0OOOoO 0O0OOOoo 0O0OOo00 0O0OOo0O 0O0OOo0o 0O0OOo 00O0OOoO0 0O0OOoOO 0O0OOoOo 0O0OOoo0 0O0OOooO 0O0OOooo 0O0Oo000 0O0Oo00 0O0Oo00O 0O0Oo00o 00O0Oo0 0O0Oo0O0 0O0Oooo 0O0Oo0O 0O0Oo0OO 0O0Oo0Oo 0O0Oo0o 0O0Oo0oO 0O0Oo0oo 0o00o00O 00O0Oo 0O0OoO00 0O0OoO0 0O0OoO0O 0OooOO 0OoO0o 0O0OoO 0O0OoOO0 0O0OoOOO 0O0OoOOo 00O0OoOo0 0O0OoOoO 0O0OoOoo 0O0Ooo00 0O0Ooo0 0O0Ooo0O 0O0Ooo0o 0O0Ooo 0O0OooO0 0O0OooO 00O0OooOO 0O0OooOo 0O0Oooo0 0O0OoooO 0O0Ooooo 0O0o0000 0O0o000 0O0o000O 0O0o000o 0O0o00 00O0o00O0 0O0o00O 0O0o00OO 0O0o00Oo 0O0o00o0 0O0o00o 0O0o00oO 0O0o00oo 0O0o0 0O0o0O00 00O0o0O0 0O0o0O0O 0O0o0O0o 0O0o0O 0O0o0OO0 0O0oo0o 0O0o0OO 0O0o0OOO 0O0o0OOo 0O0o0Oo0 000O0o0Oo 00O0o0OoO 00O0o0Ooo 00O0o0o00 00O0o0o0 00O0o0o0O 00O0o0o0o 00O0o0oO0 00O0o0oO 00O0o0oOO 00O0o0oOo 0O0o0oo 0O0o0ooO 0oOOoOO 0O0o 0O0oO000 0O0oO00 0O0oO0oO 0O0oO00O 0O0oO00o 00O0oO0 0O0oO0O0 0O0oO0O 0O0oO0OO 0O0oO0Oo 0O0oO0o0 0O0oO0o 0O0oO0oo 0o0Oo0o0 0O0oO 00O0oOO00 0O0oOO0 0o00O00O0 0O0oOO0O 0O0oOO0o 0O0oOO 0O0oOOO0 0O0oOOOo 0O0oOOo0 0Oo0OOo 00O0oOOo 0O0oOOoO 0O0oOOoo 0O0oOo00 0O0oOo0 0ooO0Ooo 0O0oOo0O 0O0oOo0o 0O0oOo 0O0oOoO0 00O0oOoO 0O0oOoOO 0O0oOoOo 0OOoOoo 0O0oOoo0 0O0oOoo 0O0oOooO 0O0oOooo 0O0oo000 0O0oo00 00O0oo00O 0O0oo00o 0O0oo0 0O0oo0O0 0O0oo0O 0O0oo0OO 0O0oo0Oo 0O0oo0o0 0O0oo0oO 0O0oo0oo 00O0oo 0O0ooO00 0O0ooOo 0O0oooo 0O0oooO 0O0ooO0 0O0oooOo 0O0ooO0O 0O0ooO0o 0O0ooO 00O0ooOO0 0O0ooOO 0O0ooOOO 0O0ooOOo 0O0ooOo0 0O0ooOoO 0O0ooOoo 0O0ooo00 0O0ooo0 0O0ooo0O 00O0ooo0o 0O0ooo 0O0oooO0 0O0oooOO 0O0oooo0 0O0ooooO 0O0ooooo 0OO0000 0OO0000o 0OoOOO 000OO000OO 00OO000Oo 00OO000o0 00OO000o 00OO000oO 00OO000oo 00OO00OO 00OO00O0 00OO00O0o 00OO00O 00OO00OOO 0OO00OOo 0OO00Oo0 0OO0ooO 0OO00Oo 0OO00OoO 0OO00Ooo 0OO00o00 0OO00o0O 0OO00o0o 00OO00oO0 0OO00oO 0OO00oOO 0OO00oOo 0OO00oo0 0OO00oo 0OO00ooO 0OO00ooo 0OO0O00o 0OO0O0O 00OO0O0OO 0OO0O0Oo 0OO0O0o0 0OO0oOo 0OO0oOO 0OO0O0o 0OO0O0oO 0OO0O0oo 0oOo00 0OO0OO0o 00OOo00 0OO0OO 0OO0OOO 0OO0OOOO 0OO0OOOo 0OO0OOo0 0OO0OOo 0OO0OOoO 0OO0OOoo 0OO0Oo00 00OO0Oo0 0OO0Oo0O 0OO0Oo0o 0Oo0Oo0O 0OO0OoO0 0OO0OoO 0OO0OoOO 0Oo0Ooo0 0OO0OoOo 0OO0Ooo0 00OO0Ooo 0OO0OooO 0OO0Oooo 0OO0o000 0OO0o00 0OO0o00O 0OO0o00o 0OO0o0 0OO0o0O0 0OO0o0OO 00OO0o0Oo 0OO0o0o0 0OO0o0o 0OO0o0oO 0OO0o0oo 0OO0o 0OO0oO00 0OO0oO0 0OO0oO0O 0OO0oO0o 00OO0oOO0 0OoOOoOo 0OO0oOOO 0OO0oOOo 0OO0oOo0 0OO0oOoO 0OO0oOoo 0OO0oo00 0OO0oo0 0OO0oo0O 00OO0oo0o 0OO0oo 0OO0ooO0 0OO0ooOO 0OO0ooOo 0OO0ooo0 0OO0ooo 0OO0oooO 0OO0oooo 0OOO000o 000OOO00 00OOO00O0 00OOO00Oo 00OOO00o0 00OOO00o 00OOO00oO 00OOO00oo 00OOO0O0O 00OOO0O0o 00OOO0O 00o00OOOOO 0OOO0OO0 0OOO0OOO 0OOO0OOo 0OOO0Oo0 0OOO0oO 0OOO0Oo 0OOO0OoO 0OOO0Ooo 0OOO0o00 00OOO0o0 0OOO0o0O 0OOO0o0o 0OOO0o 0OOO0oO0 0OOO0oOO 0OOO0oOo 0OOO0oo0 0OOO0oo 0OOO0ooO 00OOO0ooo 0OOO 0OOOO00O 0OOOO00o 0OOOO0 0OOOOoO 0OOOOo0 0OOOOoo 0OOOO0O 0OOOO0OO 00OOOO0Oo 0OOOO0o0 0OOOO0oO 0OOOO0oo 0OOOOO00 0OOOOO0 0OOOOO0o 0OOOOO 0OOOOOO 0OOOOOOO 00OOOOOOo 0OOOOOo0 0OOooOo 0OOoooo 0OOOOOo 0OOOOOoO 0OOOOOoo 0OOOOo00 0OOOOo0O 0OOOOo0o 00OOOOo 0OOOOoO0 0OOOOoOO 0OOOOoOo 0OOOOoo0 0OOOOooO 0OOOOooo 0OOOo000 0OOo000 0OOOo00 00OOOo00O 0OOOo00o 0OOOo0 0ooOOo00 0OOOo0O0 0OOOo0O 0OOOo0OO 0OOOo0Oo 0OOOo0o0 0OOOo0o 00OOOo0oO 0OOOo0oo 0OOOo 0OOOoO00 0OOOoO0 0OOOoO0O 0o0ooo0OO 0OOOoO0o 0OOOoO 0OOOoOO0 00OOOoOO 0OOOoOOO 0OOOoOOo 0OOOoOo0 0OOOoOo 0OOOoOoO 0OOOoOoo 0ooO00O0 0OOOoo00 0OOOoo0 000o00O0oO0 00OOOoo0O 00OOOoo0o 00OOOoo 00OOOooO0 00OOOooO 00o0OOoOoo 00OOOooOO 00OOOooOo 00OOOooo0 00OOOooo 0OOOoooO 0OOOoooo 0OOo0000 0OOo000O 0OOo000o 0OOo00O0 0OOo00O 0OOo00OO 0OOo00Oo 00OOo00o0 0OOo00o 0OOo00oO 0OOo00oo 0ooOo 0OOo0 0OOo0O00 0OOo0OO 0OOo0Oo 0OOoo00 00OOo0O0 0OOo0O0O 0OOo0O0o 0OOoOOoO 0OOo0OO0 0OOo0OOO 0OOo0OOo 0OOo0Oo0 0OOo0OoO 0OOo0Ooo 00OOo0o00 0OOo0o0 0OOo0o0O 0OOo0o0o 0OOo0o 0OOo0oO0 0OOo0oO 0OOo0oOO 0OOo0oOo 0OOo0oo0 00OOo0oo 0OOo0ooO 0OOo0ooo 0OOoO000 0OOoO00 0OOoO00O 0OOoO00o 0OOoO0 0OOoO0O0 0OOoO0o 00OOoO0O 0OOoO0OO 0OOoO0Oo 0OOoO0o0 0OOoO0oO 0OOoO0oo 0OOoO 0OOoOO00 0OOoOO0O 0OOoOO0o 00OOoOO 0OOoOOO0 0OOoOOO 0OOoOOOO 0OOoOOOo 0OOoOOo0 0OOoOOo 0OOoOOoo 0OOoOo00 0OOoOo0 00OOoOo0O 0OOoOo0o 0OOoOo 0OOoOoO0 0oO0OO0 0OOoOoO 0OOoOoOO 0OOoOoOo 0OOoOoo0 0OOoOooO 00OOoOooo 0OOoo000 0OOoo00O 0OOoo00o 0OOoo0 0OOoo0O0 0OOoo0O 0OOoo0OO 0OOoo0Oo 0OOoo0o0 000OOoo0o 00OOoo0oO 00OOoo0oo 00OOoo 00OOooO00 00OOooO0 00OOooO0O 00OOooO0o 00OOooO 00OOooOO0 00OOooOO 0OOooOOO 0OOooOOo 0OOooOo0 0OOooOoO 0OOooOoo 0OOooo00 0OOooo0 0OOooo0O 0OOooo0o 00OOooo 0OOoooO0 0OOoooO 0OOoooOO 0OOoooOo 0OOoooo0 0OOooooO 0OOooooo 0Oo00000 0Oo0000O 00Oo0000o 0Oo000 0Oo000O0 0Oo000O 0Oo000OO 0Oo000Oo 0Oo000o0 0Oo000o 0Oo000oO 0Oo000oo 00Oo00 0Oo00O00 0Oo00O0 0Oo0o0Oo 0Oo00O0O 0Oo00O0o 0Oo00O 0Oo00OO0 0Oo0o0o 0Oo00Oo 00Oo00OO 0Oo00OOO 0Oo00OOo 0Oo00Oo0 0Oo0o0O0 0Oo00OoO 0Oo00Ooo 0Oo00o00 0Oo00o0 0Oo00o0O 00Oo00o0o 0Oo00o 0Oo00oO0 0Oo00oOO 0Oo00oo0 0Oo00oo 0Oo00ooO 0Oo00ooo 0Oo0 0Oo0O000 00Oo0O00 0Oo0O00O 0Oo0O00o 0Oo0O0 0Oo0O0O0 0Oo0O0O 0Oo0O0OO 0Oo0O0Oo 0Oo0O0o0 0Oo0O0o 00Oo0O0oO 0Oo0O0oo 0o00oO00 0o00OO00 0Oo0O 0Oo0OO00 0Oo0OO0 0Oo0OO0O 0Oo0OO0o 0Oo0OO 00Oo0OOO0 0Oo0OOOO 0Oo0OOOo 0Oo0OOo0 0Oo0OOoO 0Oo0OOoo 0Oo0Oo00 0Oo0Oo0 0Oo0Oo0o 0Oo0Oo 000Oo0OoO0 00Oo0OoO 00Oo0OoOo 00Oo0Ooo 00Oo0OooO 00Oo0Oooo 00Oo0o000 00Oo0o00 00Oo0o00O 00Oo0o00o 00Oo0o0 0Oo0o0O 0Oo0o0o0 0Oo0o0oO 0Oo0o0oo 0Oo0o 0Oo0oO00 0Oo0ooO 0Oo0oOO 0Oo0oo0 00Oo0ooo 0Oo0oO0 0Oo0oO0O 0Oo0oO0o 0Oo0oO 0Oo0oOO0 0Oo0oOOO 0Oo0oOOo 0Oo0oOo0 0Oo0oOo 00Oo0oOoO 0Oo0oOoo 0Oo0oo00 0Oo0oo0O 0Oo0oo0o 0Oo0oo 0Oo0ooO0 0Oo0ooOO 0Oo0ooOo 0Oo0ooo0 00Oo0oooO 0Oo0oooo 0Oo 0OoO0000 0OoO000 0OoO000O 0OoO000o 0OoO00O0 0OoO00O 0OoO00OO 00OoO00Oo 0OoO00o0 0OoO00o 0OoO00oO 0OoO00oo 0OoO0 0OoO0O00 0OoO0Oo 0OoO0O0 0OoO0O0O 00OoO0O0o 0OoO0O 0OoO0OO0 0OoO0OO 0OoO0OOO 0OoOo00O 0OoO0OOo 0OoO0Oo0 0OoO0OoO 0OoO0Ooo 00OoO0o00 0OoO0o0 0OoO0o0O 0OoO0o0o 0OoO0oO0 0OoO0oo 0OoO0oO 0OoO0oOO 0OoO0oOo 0OoO0oo0 00OoO0ooO 0OoO0ooo 0OoO 0OoOO000 0OoOOo0 0OoOOOO 0OoOO0O 0OoOOoo 0OoOOoO 0OoOOO0 00OoOOOo 0OoOoOo 0OoOoOO 0OoOO00 0OoOO00O 0OoOO00o 0OoOO0 0OoOO0O0 0OoOO0OO 0OoOO0Oo 000OoOO0o0 00OoOO0o 00OoOO0oO 00OoOO0oo 00OoOo 00OoOO 00OoOOO0O 00OoOOO0o 00OoOOOO0 00OoOOOOO 00OoOOOOo 0OoOOOo0 0OoOOOoO 0OoOOOoo 0OoOOo00 0OoOOo0O 0OoOOo0o 0OoOOo 0OoOOoO0 0OoOOoOO 00OoOOoo0 0OoOOooO 0OoOOooo 0OoOo000 0OoOooo 0OoOoo0 0OoOo00 0OoOo00o 0OoOo0 0OoOo0O0 00OoOo0o 0OoOo0O 0OoOo0OO 0OoOo0Oo 0OoOo0o0 0OoOo0oO 0OoOo0oo 0OoOoO00 0OoOoO0 0OoOoO0O 00OoOoO0o 0OoOoO 0OoOoOO0 0OoOoOOO 0OoOoOOo 0OoOoOo0 0OoOoOoO 0OoOoOoo 0OoOoo00 0OoOoo0O 00OoOoo0o 0OoOoo 0OoOooO0 0OoOooO 0OoOooOO 0OoOooOo 0OoOooo0 0OoOoooO 0OoOoooo 0Ooo0000 00Ooo000 0Ooo000O 0Ooo000o 0Ooo00 0Ooo00O0 0Ooo00O 0Ooo00OO 0Ooo00Oo 0Ooo00o0 0Ooo00o 00Ooo00oO 0o00oo00o 0Ooo00oo 0Ooo0 0Ooo0O00 0Ooo0O0 0Ooo0O0O 0Ooo0O0o 0Ooo0O 0Ooo0OO0 00Oooo00 0Ooo0oO 0Ooo0Oo 0Ooo0OO 0o000O0OO 0o000oO0O 0Ooo0OOO 0Ooo0OOo 0Ooo0OoO 0Ooo0Ooo 00Ooo0o00 0Ooo0o0 0Ooo0o0o 0Ooo0o 0Ooo0oO0 0Ooo0oOO 0Ooo0oOo 0Ooo0oo0 0Ooo0oo 0Ooo0ooO 00Ooo0ooo 0o0oo 0Ooo 0OooO000 0OooO0O 0Ooooo0 0OooooO 0OoooOO 0OoooOo 0OooO00 0OooO00O OooO00o OooO0O0 OooO0OO OooO0Oo OooO0o0 OooO0o OooO0oO OooO0oo OooO 0OooOO00 OooOO0 OooOO0O OooOO0o OooOOO0 OooOOO OooOOOO OooOOOo OooOOo0 OooOOo 0OooOOoO OooOOoo OooOo00 OooOo0 OooOo0O OooOo0o OooOo OooOoO0 OooOoO OooOoOO 0OooOoOo OooOoo0 OooOoo OooOooO OooOooo Oooo000 Oooo00O Oooo00o Oooo0 Oooo0O0 0Oooo0O Oooo0OO Oooo0o0 Oooo0o Oooo0oO Oooo0oo Oooo OoooO00 OoooO0 OoooO0O 0OoooO0o OoooO OoooOO0 o000oOoO OoooOOO OoooOOo OoooOo0 OoooOoO OoooOoo Ooooo00 0Ooooo0O Ooooo0o OooooO0 OooooOO OooooOo Oooooo0 Oooooo OoooooO Ooooooo o0OoOo0 0o0OoO0O ooOO o00O0O o00Oo0 o00Ooo o00o0O o00ooo oo000o o00oO0o o00oO0O 0o0oo000 o0ooOO0 o0ooOOo o0ooOoO o0OOO0o o0Oo0oo o0OO00O oo0o0Oo o0O0O00 o000OOo 00oo0oOoO 0ooo0Ooo 0ooOo00O 0o0OoOO0 0o0O00oo 0o0ooo00 0o000OOoo 0o000OOOo 0o000OOOO 0o000OOO0 0o0000000 o000000 o000000O o000000o o00000 o00000O0 o00000O o00000OO o00000Oo o00000o0 0o00000o o0000Ooo o00000oO o00000oo o0000 o0000O00 o0000oo o0000oO o0000O0 o0000O0O 0o0000O0o o000OO o0000O o0000OO0 o0000OO o0000OOO o0000OOo o0000Oo0 o0000Oo o0000OoO 0o0000o00 o0000o0 o0000o0O o0000o0o o0000o o0000oO0 o0000oOO o0000oOo o0000oo0 o0000ooO 0o0000ooo o000 o000O000 o000OoO o000O0o o000Ooo o000O0O o000Oo0 o000O00 o000O00O 0o000O00o o000O0 o000O0Oo o000OO0O o000O0O0 o000O0o0 o000O0oO o000O0oo o000O o000OO00 0o000OO0 o0OoO0o o000OO0o o000OOO o000OOo0 o000OOoO o000Oo00 o000Oo0O o000Oo0o o000Oo 0o000OoO0 o000OoOO o000OoOo o000Ooo0 o000OooO o000Oooo o000o000 o000o00 o000o00O o000o00o 0o000o0 oooo00o o000o0O0 o000o0O o000o0OO o000o0Oo o000o0o0 o000o0o o000o0oO o000o0oo 00o000o 0o000oO00 0o000oO0 0o000oO0o 0o000oO 0o000oOO0 0o000oOO 0o000oOOO 0o000oOOo 0o000oOo0 0o000oOo o000oOoo o000oo00 o000oo0 o000oo0O o000oo0o o000oo o000ooO0 o000ooO o000ooOO 0o000ooOo o000ooo0 o000ooo o000oooO o000oooo o00 o00O0000 o0O0ooO o00oOoo o00O000 0o00O000O o00O000o o00O00 o00O00O oOO00O o00O00OO o00O00Oo o00O00o0 o00O00o o00O00oO 0o00O00oo oo00o o00O0 o00O0O00 o00O0O0 o00O0O0O o00O0O0o o00O0OO0 oo0o0O0 o00O0OO 0o00Oo00O o00O0OOO o00O0OOo o00O0Oo0 oo0oOO0 o00O0Oo o00O0OoO o00O0Ooo o00O0o00 o00oOOo 0o00oOOO o00O0o0 o00O0o0O o00O0o0o o00O0o o00O0oO o00O0oOO o00O0oOo o00O0oo0 o00O0oo 0o00O0ooO o00O0ooo o00O o00OO000 o00OO00O o00OO00o o00OO0 o00OO0O0 o00OO0O o00OO0OO 0o00OO0Oo o00OO0o0 o00OO0o o00OO0oO o00OO0oo oo0O o00OO o00OOO00 o00OOO0 o00OOO0O 0o00OOO0o o0o0Oo o00OOO o00OOOO0 o00OOOO o00OOOOo oOooo0o o00OOOo0 o00OOOo o00OOOoO 00o00OOOoo 0o00OOo00 0o00OOo0 0o00OOo0O 0o00OOo0o 0o00OOo 0o00OOoO0 0o00OOoO 0o00OOoOO 0o00OOoOo 0o00OOoo0 o00OOoo o00OOooO o00OOooo o00OoOoO o00Oo000 o00Oo00 o00Oo00o o00Oo0O0 o00Oo0O 0o00Oo0OO o00Oo0Oo o00Oo0o0 o00Oo0o o00Oo0oO o00Oo0oo o0oOO o00Oo o00OoO00 o00OoO0 0o00OoO0O o00OoO0o o00OoO o00OoOO0 o00OoOO o00OoOOO o00OoOOo o00OoOo0 o00OoOo o00OoOoo 0o00Oooo0 o00Ooo00 o00Ooo0 o00Ooo0O o00Ooo0o o00OooO0 o00OooO o00OooOO o00OooOo o0O00o0 0o00Oooo o00OoooO o00Ooooo o00o0000 o00o000 o00o000O o00o000o oo00oO o00o00 o00o00O0 0o00o00OO o00o00Oo o00o00o0 o00o00o o00o00oO o00o00oo o00o0 o00o0O00 o00o0O0 o00o0O0O 0o00o0O0o o00o0OO0 o00o0OO o00o0OOO o00o0OOo o00o0Oo0 o00o0Oo o00o0OoO o00o0Ooo o00o0o00 0o00o0o0 o00o0o0O o00o0o0o o00o0o o00o0oO0 o00o0oO o00o0oOO o00o0oOo o00o0oo0 o00o0oo 0o00o0ooO o00o0ooo o00o o00oo000 o00oO000 o00oO00O o00oO00o o00oOo o00oO0 o00oO0O0 00o00oO0OO 0o00oO0Oo 0o00oO0o0 0o00oO0oO 0o00oO0oo 0o00oO 0o00oOOoo 0o00oOO00 0o00oOO0 0o00oOO0O 0o00oOO0o o0oOOo o0ooOO o00oOO o00oOOO0 o00oOOOO o00oOOOo o00oOOo0 o00oOOoO o00oOo00 0o00oOo0 o00oOooO o00oOo0O o00oOo0o o00oOoO0 o00oOoO o00oOoOO o00oOoOo o00oOoo0 o00oOooo 0o00oo00 o00oo00O o00oo0 o00oo0OO o00oo0O0 o00oo0O o00oo0Oo o00oo0o0 o00oo0o o00oo0oO 0o00oo0oo o0O0o o00oo o00ooO00 o00ooO0 o00ooO0O o00ooO0o o00ooO o00ooOO0 o00ooOO 0o00ooOOO o00ooOOo o00ooOo0 o00ooOo o00ooOoO o00ooOoo o00ooo00 o00ooo0 o00ooo0O o00ooo0o 0o00oooO0 o00oooO o00oooOO o00oooOo o00oooo0 o00oooo o00ooooO o00ooooo o0 o0O00000 0o0O0000 o0O0000O o0O0000o o0O000 o0O000O o0OoOoOo o0O000Oo o0OoOoOO o0O000o0 o0O000o 0o0O000oO o0ooOoOO o0O000oo o0O00 o0O00O0 o0OoO00O o0O00O0o o0O00O o0O00OO o0O00OOO 0o0O00Oo0 o0O00Oo o0oO0Ooo o0O00OoO o0O00Ooo o0O00o00 o0O00o0O o0O00o0o o0O00o o0O00oO0 00o0O00oO 0o0O00oOO 0o0O00oOo 0o0O00oo0 0o0Oo0oOO 0o0O00ooO 0o0O00ooo 0o0O0 0o0ooOOOo 0o0O0O00O 0o0O0O0 o0O0O0O o0oO0O0o o0O0oo0o o0O0O0Oo o0O0O0o0 o0O0O0o o0O0O0oO o0O0O0oo o0ooO 0o0O0O o0O0OO0 o0O0OO0O o0O0OO o0O0OOO0 o0O0OOO o0O0OOOo o0O0OOo o0O0OOoO o0O0OOoo 0o0O0Oo00 o0OooO0 o0O0Oo0 o0O0Oo0O o0O0Oo0o o0O0Oo o0O0Oooo o0O0OoO0 oo0OOoo o0O0OoO 0o0O0OoOO o0O0OoOo o0O0Ooo0 o0O0Ooo o0O0OooO o0O0o000 o0O0o00 o0O0o00O o0O0o00o o0O0o0 0o0O0o0O0 o0O0o0O o0O0o0OO o0O0o0Oo o0O0o0o0 o0O0o0o o0oOo0O0 o0O0o0oO o0O0o0oo o0O0oo0O 0o0O0oO00 oooOO0 o0O0oO0 o0O0oO0O o0O0oO0o o0O0oO o0O0oOO0 o0O0oOO o0O0oo00 o0O0oOOO 0o0O0oOOo o0O0oOo0 oo0oOOo o0O0oOo o0O0oOoO o0O0oOoo o0O0oo0 o0O0oo o0O0ooO0 o0O0ooOO 0o0O0ooOo o0O0ooo0 o0O0ooo o0O0oooO o0O0oooo o0O o0OO000 o0OO000o oo0oO0 oo0ooO 0o0OO00 o0OO00OO o0OO00oo o0OO00Oo o0OO00o0 o0OoOoO o0OO00o o0OO0 o0OO0O0 o0OO0O0O 00o0OO0O0o 0o0OO0O 0o0OOoOOo 0o0OOoOoO 0o0OO0OO0 0o0OO0OO 0o0OOoOO0 0o0OO0OOO 0o0OO0OOo 0o0OO0Oo0 0o0OO0Oo o0OO0OoO o0OOooO0 o0OO0Ooo o0OO0o00 o0OO0o0 o0OO0o0O o0OO0o0o o0OO0o o0OO0oO0 0o0OO0oo o0OO0oO o0OO0oOO o0OOoooO o0OO0oOo o0OO0oo0 o0OO0ooO o0OO0ooo o0OO o0OOO00 0o0OOO00O o0OOO00o o0OOO0 o0OOO0O0 o0OOO0O o0OOO0OO o0OOO0Oo o0OOO0o0 o0OOO0oO o0OOO0oo 0o0OOO o0OOOOoO o0OOOO00 o0OOOO0 o0OOOO0o o0OOOO o0OOOOO0 o0OOOOO o0OOOOOO o0OOOOOo 0o0OOOOo0 o0OOOOo o0OOOOoo o0OOOo00 o0OOOo0 o0OOOo0O o0OOOo0o o0OOOo o0OOOoO0 o0OOOoO 0o0OOOoOO o0OOOoOo o0OOOoo0 o0OOOoo o0OOOooO o0OOOooo o0OOo000 o0OOo00 o0OOo00O o0OOo00o 0o0OOo0 o0OOo0O0 o0OooOo o0OOo0O o0OOo0OO o0OOo0Oo o0OOo0o0 o0OOo0o o0OOo0oO o0OOo0oo 0o0OOo o0OOoO00 o0OOoO0 o0OOoO0O o0OOoO0o o0OOoO o0OOoOO o0OOoOOO o0OOoOo0 o0OOoOo 0o0OOoo00 o0OOoo0 o0OOoo0O o0OOoo0o o0OOoo o0OOooO o0OOooOO o0OOooOo o0OOooo0 o0OOooo 00o0OOoooo 0o0Oo0000 0o0Oo000 0o0Oooo0O 0o0Oo00O0 0o0Oo000O 0o0Oo000o 0o0Oo00 0o0Oo00OO 0o0Oo00Oo 0o0oooOoo o0Oo00o0 o0Oo00o o0Oo00oO o0Oo00oo o0Oo0 o0ooO0O0 o0Oo0O00 o0Oo0O0 o0Oo0O0O 0o0Oo0O0o o0Oo0O o0Oo0OO0 o0Oo0OO o0oOooO0 o0ooOOOO o0oOo000 o0Oo0OOO o0oOo0o0 o0oOoo00 0o0oO0OOo o0Oo0OOo o0Oo0Oo0 o0Oo0Oo o0Oo0OoO o0Oo0oOo o0Oo0Ooo o0Oo0o00 o0Oo0o0O o0Oo0o0o 0o0Oo0o o0Oo0oO0 o0Oo0oO o0Oo0oo0 o0Oo0ooO o0Oo0ooo o0Oo o0OooOoo o0OoO000 o0OoO0 0o0OoO0O0 o0oO0O00 o0OoO0OO o0ooOOO0 o0OoO0Oo o0OoO0o0 o0OoO0oO o0OoO0oo o0OoO o0OoOO00 0o0OoOO0O o0OoOO0o o0OoOO o0OoOOoO o0OoOOO0 o0OoOOO o0OoOOOO o0OoOOOo o0OoOOo0 o0OoOOo 0o0OoOOoo o0OoOo00 o0OoOo0O o0ooOOoo o0OoOo0o o0OoOo o0OoOoO0 o0OoOoo0 o0OoOoo o0OoOooO 0o0OoOooo o0Ooo000 o0Ooo00 o0Ooo00O o0oOO0Oo o0oOoOoo o0Ooo00o o0Ooo0 o0Ooo0O0 o0Ooo0O 0o0Ooo0OO o0oOOOoo o0OoooO0 o0oOOO0o o0Ooo0Oo o0Ooo0o0 o0Ooo0o o0Ooo0oO o0Ooo0oo o0Ooo 00o0OooO00 0o0OooO0O 0o0OooO0o 0o0OooO 0o0OooOO0 0o0OooOO 0o0OooOOO 0o0OooOOo 0o0OooOo0 0o0OooOoO 0o0Oooo00 o0Oooo0 o0Oooo0o o0Oooo o0OoooO o0OoooOO o0OoooOo o0Ooooo0 o0Ooooo o0OooooO 0o0Oooooo o0o0000 o0o0o00O o0o0000o o0o000 o0o000O0 o0o000O o0o000OO o0o000Oo o0o000o0 0o0o000o o0o000oO o0o000oo o0o00 o0o00O00 o0o00O0 o0o00O0O o0o00O0o o0o00O o0o00OO0 0o0o00OO o0o00OOO o0o00OOo o0o00Oo0 o0o00Oo o0o00OoO o0o00Ooo o0o00o00 o0o00o0 o0o00o0O 0o0o00o0o o0o00o o0o00oO0 o0o00oO o0o00oOO o0o00oOo o0o00oo0 o0o00oo o0o00ooO o0o00ooo 0o0o0 o0o0O000 o0o0O00 o0o0O00O o0o0O00o o0o0O0 o0o0O0O0 o0o0O0O o0o0Oo00 o0o0O0OO 0o0o0O0Oo o0o0O0o0 o0o0O0o o0o0O0oO o0o0O0oo oO0Oo oO0OO o0ooo o0o0O o0o0OoO0 0o0o0OO00 o0o0OO0 o0o0OO0O o0o0OO0o o0o0OO o0o0OOO0 o0o0OOO o0o0OOOO o0o0OOOo o0o0OOo0 0o0o0OOo o0o0OOoO o0o0OOoo o0o0Oo0 o0o0Oo0O o0o0Oo0o o0o0OoO o0o0OoOO o0o0OoOo o0o0Ooo0 000o0o0Ooo 00o0o0OooO 00o0o0Oooo 00o0o0o000 00o0o0o00 00o0o0o00o 00o0o0o0 00o0o0o0O0 00o0o0o0O 00o0o0o0OO 00o0o0o0Oo 0o0o0o0o0 0o0o0o0o 0o0o0o0oO 0o0o0o0oo 0o0o0o 0o0o0oO00 0o0o0oO0 0o0o0oO0O 0o0o0oO0o 00o0oo00 0o0o0oO 0o0o0oOO0 0o0o0oOO 0o0o0oOOO 0o0o0oOOo 0o0o0oOo0 0o0o0oOo 0o0o0oOoO 0o0o0oOoo 00o0o0oo00 0o0o0oo0 0o0o0oo0O 0o0o0oo0o 0o0o0oo 0o0o0ooO0 0o0o0ooO 0o0o0ooOO 0o0o0ooOo 0o0o0ooo0 00o0o0ooo 0o0o0oooO 0o0o0oooo 0o0o 0o0oO0000 0ooooooO 0o0oO000 0o0oO000O 0o0oO000o 0o0oO00 00o0oO00O0 0o0oO00O 0o0oO00Oo 0o0oO00OO 0o0oO00o0 0o0oO00o 0o0oO00oO 0o0oO00oo 0o0oO0 0o0oO0O0 00o0oO0O 0o0oO0OO0 0o0oO0OO 0o0oO0OOO 0o0oO0Oo 0o0oO0OoO 0o0oO0o00 0o0oO0o0 0o0oO0o0o 0o0oO0o0O 00o0oO0o 0o0oO0oO0 0o0oO0oO 0o0oO0oOO 0o0oO0oo0 0o0oO0oo 0o0oO0ooO 0o0oO0ooo 0o0oO 0o0oOO000 00o0oOO00 0o0oOO00O 0o0oOO00o 0o0oOO0 0o0oOO0O0 0o0oOO0O 0o0oOo0oO 0o0oOo0oo 0o0oOO0OO 0o0oOO0o0 00o0oOO0o 0o0oOO0oO 0o0oOO0oo 0o0oOOO00 0o0oOOO0 0o0oOOO0O 0o0oOOO 0o0oOOOO0 0o0oOOOO 0o0oOOOOO 00o0oOOOOo 0o0oOOOo0 0o0oOOOo 0o0oOOOoO 0o0oOOo00 0o0oOOo0 0o0oOOo0O 0o0oOOo0o 0o0oOOoO0 0o0oOOoO 0o0oOoO00 o0oOOoOO o0oOooOO o0oOOoOo o0oOOoo0 o0oOOoo o0oOOooO o0oOOooo o0oOo00 o0oOo00O 0o0oOo00o o0oOo0 o0oOo0O o0oOo0OO o0oOo0Oo o0oOo0o o0oOo o0oOoO0 o0oOoO0o o0oOoOo0 0o0oOoO0O o0oOoO o0oOoOO0 o0oOoOO o0oOoOOO o0oOoOOo o0oOoOo o0oOoOoO o0oOoo0 o0oOoo0O 0o0oOoo0o o0oOoo o0oOooO o0oOooOo o0oOooo0 o0oOooo o0oOoooO o0oOoooo o0oo0000 o0oo000O 0o0oo000o o0oo00O0 o0oo00O o0oo00OO o0oo00Oo o0oo00o0 o0oo00o o0oo00oO o0oo00oo o0oo0 0o0oo0O00 o0oo0O0 o0oo0O0O o0oo0O0o o0oo0o o0oo0O o0oo0OO0 o0oo0OO o0oo0OOO o0oo0OOo 0o0oo0Oo0 o0oo0Oo o0oo0OoO o0oo0Ooo o0oo0o00 o0oo0o0 o0oo0o0O o0oo0o0o o0oo0oO0 o0oo0oO 0o0oo0oOO o0oo0oOo o0oo0oo0 o0oo0oo o0oo0ooO o0oo0ooo o0ooO000 o0ooO00 o0ooO00O o0ooO00o 0o0ooO0 o0ooO0O o0ooO0OO o0ooO0Oo o0ooO0o0 o0ooO0o o0ooO0oO o0ooO0oo o0ooOO0O o0ooOO0o 00o0ooOOO 0o0ooOOoO 0o0ooOo00 0o0ooOo0 0o0ooOo0o 0o0ooOo0O 0o0ooOo 0o0ooOooO 0o0ooOoO0 0o0ooOoOo 0o0ooOoo0 o0ooOoo o0ooOooo o0ooo000 o0ooo00O o0ooo00o o0ooo0 o0ooo0O o0ooo0o0 o0ooo0o 0o0ooo0oO o0ooo0oo o0oooO00 o0oooO0 o0oooO0o o0oooO0O o0oooO o0oooOO0 o0oooOO o0oooOOo 0o0oooOOO o0oooOo0 o0oooOo o0oooOoO o0oooo00 o0oooo0 o0oooo0O o0oooo0o o0oooo o0ooooO0 0o0ooooO o0ooooOo o0ooooo0 ooo0Oo0 o0ooooo o0oooooO o0oooooo o oO00000 oO00000o 0oO0000 oO0000O oO0000Oo oO0000o0 oO0000o oO0000oO oO0000oo oO000 oO000O0 oO000O0O 0oO0Ooo00 oO0Ooooo oO000O0o oO0o0o oO000O oO0OoOO0 oO0OOooo oO0OoOOO oO0OOoO0 oO0Oo0oo 0oO000OOO oO0OO0oo oO0OOooO oO000OOo oO0OoOoO ooOOOOoo oO0OOo0o oO000Oo0 oO000Oo oO0OO0OO 0oO0OoOoo oO0OOoo0 oO000OoO oO0OOo0O oO000Ooo oO000o00 oO000o0 ooOOOOOo oO000o0o oO000o 0oO0Oo0OO oO000oO0 oO000oO oO0Ooo0O oO000oOO oO0Ooo0o oO000oOo oO000oo0 oO000oo oO0Oo0Oo 00oO000ooO 0oO0Oo0O0 0oO000ooo 0oO00 0oO00O00 0oO0O0o0o 0ooOOoooO 0oO00O00o 0oO00O0 0oO00O0O 0oO00O0Oo oO0O0OoO ooOOooOo oO00O0o0 oO00O0o oOo00OO0 oO00O0oO oO0O0OOo oO00O0oo oO00O 0oO00OO0 ooOOoOoO oO0O0OOO oO00OO0O oO00OO oO00OOO oO00OOOo oOo00Oo0 ooOOoOOo oO00OOo0 0oO00OOo oO0oOOO0 oO00OOoO oOOoOoOO oO00OOoo oO00Oo00 oO00Oo0 oO00Oo0O oO00Oo0o oO00Oo 0oO00oOOO oO00OoO0 oO00OoO oOOoOOO0 oO00OoOO oO0oOOOo oO00OoOo oO00Ooo0 oO00Ooo oO00OooO 0oO00Oooo oO0OOoOo oO00o000 oO00o00 oO0OooOO oO0OoOo0 oO0OOO00 oO00o00O oO0OOoOO oO00o00o 0ooOO0O ooOOo0 oO00o0 oO0OOOoo oO00o0O0 oO00o0O oO0OOOOo oO00o0OO oO0OOOoO oO00o0Oo 0oO0OoO0O oO0OOO0o oO00o0o0 oO00o0o oO0OOOo0 oO00o0oO oO0OOO0O oO00o0oo oO00o oO0OO0oO 0oO0OO000 oOo00o0o oO00oO00 oO00oO0 oO0OoooO oOo00ooO oO00oO0O oO0OooOo oOo00ooo oO00oO0o 0oO00oO oO00oOO0 oO00oOO oO0OO00o oO00oOOo oOo00oO0 oO00oOo0 oO00oOo oO0OO00O ooOOOOoO 00oOo00oOO 0oO00oOoO 0oOo00oOo 0oO00oOoo 0oO0OOOOO 0oO00oo00 0oO00oo0 0oO0OO0o0 0oO00oo0O 0oO00oo0o 0oO00oo oO00ooO0 oO00ooO oOo000Oo oO00ooOO oO00ooOo oOo0000O oO00ooo0 oO00ooo oOo000oo 0oO00oooO oOo000o0 oO00oooo oO0 oO0O000 oO0Oo00O ooOOoOo0 oO0O000o oO0O00 oO0O00O 0oO0O00Oo oO0O00o0 oO0O00o oO0O00oO oO0O00oo oOoo0 oO0O0 oO0O0O00 oO0O0O0 ooOOOoO0 0oO0O0O0O ooOOOoo0 oO0O0O0o oO0O0o oO0O0O oO0O0OO oOo0oooO ooOOOoOo oO0O0Oo0 oO0O0Oo 0oO0O0o0 oO0O0o0O oO0O0oO0 oO0O0oO oOo0o0oO ooOOO0Oo oO0O0oOO oO0O0oOo oOo00OOo oO0O0oo0 0oO0O0oo oOo00OOO ooOOO00O oO0O0ooO oO0O0ooo ooo0o oO0O oO0OO00 oO0OO0O oO0OO0Oo 0oO0OO0o oO0OOO0 oO0OOO oO0OooO0 oO0OOOO0 oO0OOOO oO0OOOo oO0OOo0 oO0OOo oO0OOoO 0oO0OOoo oO0Oo00 oO0Oo0 oO0Oo0O oO0Oo0o0 oO0Oo0o oO0OoO00 oO0OoO0 oO0OoO oO0OoOO 0oO0OoOo oO0Ooo0 oO0Ooo oO0OooO oO0Oooo oO0o0000 oO0o000 oO0o000O ooOOoOoo oO0o000o 00oO0o00 0oO0o0oo0 0oO0o00O0 0oO0o00O 0oO0o00OO 0oO0o00Oo 0oO0o00o0 0oO0o00o 0oO0o00oO 0oO0o00oo 0oO0o0 oO0o0O00 oO0o0O0 oO0o0O0O oO0o0O0o oO0o0O oO0o0OO0 oO0o0OO oO0o0OOO oO0o0OOo 0oO0o0Oo0 oO0o0Oo oO0o0OoO oO0o0Ooo oO0o0o00 oO0o0o0 oO0o0o0O oO0o0o0o oO0o0oO0 oO0o0oO 0oO0o0oOO oO0o0oOo oO0o0oo oO0o0ooO oO0o0ooo oO0o oO0oO000 oO0oO00 oOo00O0O ooOOoOO0 0oO0oO00O oO0oO00o oO0oO0 oO0oO0O0 oO0oO0O oO0oO0OO oOo00OoO ooOOoOOO oO0oO0Oo oO0oO0o0 0oO0oO0o oO0oO0oO oO0oO0oo oOooo oO0oO oO0oOoOO oO0oOO00 oO0oOO0 oO0oOO0O oO0oOO0o 0oO0oOO oO0oOOO oO0oOOOO oO0oOOo0 oO0oOOo oO0oOOoO oO0oOOoo oO0oOo00 oO0oOo0 oO0oOo0O 0oO0oOo0o oO0oOo oO0oOoO0 oO0oOoO oO0oOooo oO0oOoOo oO0oOoo0 oO0oOoo oO0oOooO oO0oo000 0oO0oo00 oO0oo00O oO0oo00o oO0oo0 oO0oo0O0 oO0oo0O oO0oo0OO oO0oo0Oo oO0oo0o0 oO0oo0o 0oO0oo0oO oO0oo0oo oO0oo oO0ooO00 oO0ooO0 oO0ooO0O oO0ooO0o oO0ooO oO0ooOO0 oO0ooOO 00oO0ooOOO 0oO0ooOOo 0oO0ooOo0 0oO0ooOo 0oO0ooOoO 0oO0ooOoo 0oO0ooo00 0oO0ooo0 0oO0ooo0O 0oO0ooo0o 0oO0ooo oOo00o0O oO0oooO0 oO0oooO oO0oooOO oOo00oo0 oO0oooOo oOo000OO oO0oooo0 oO0oooo 0oO0ooooO oOo00o00 oO0ooooo oO oOO00000 oOO0000 oOO0000O oOO0000o oOO000 oOO000O0 0oOO000O oOO000OO oOO000Oo oOO000o0 oOO000o oOO000oO oOO000oo oOO00 oOO00O00 oOO00O0 0ooooOO00 oOO00O0O oOO00O0o oOO00OO0 oOO00OO oOO00OOO oOO00OOo oOO00Oo0 oOO00Oo ooooO000 0oOO00OoO ooooOoOo oOO00Ooo oOO00o00 oOO00o0 oOO00ooo oOO00o0O oOO00o0o oOO00o oOO00oO0 0oOO00oO ooooOOo0 ooooO0oo oOO00oOO oOO00oOo oOO00oo oOO00ooO oOO0 ooooOoOO oOO0O000 0oOO0O00 oOO0O00O oOO0O00o oOO0O0 oOO0O0O0 oOO0O0O oOO0O0OO oOO0O0Oo oOO0O0o0 oOO0O0o 0oOO0O0oO oOO0O0oo oOO0O oOO0OO0 oOO0OO0O oOO0OO0o oOO0OO oOO0OOO oOO0OOOO oOO0OOOo 0oOO0OOo0 oOO0OOo oOO0OOoO oOO0OOoo oOO0Oo00 oOO0Oo0 oOO0Oo0O oOO0Oo0o oOO0Oo oOO0OoO0 00oOO0OoO 0oOO0OoOO 0oOO0OoOo 0oOO0Ooo0 0oOO0Ooo 0oOO0OooO 0oOO0Oooo 0oOO0o00 0ooooOOoo 0oOO0o00o 0oOO0o0 oOO0o0O0 oOO0o0O oOO0o0OO oOO0o0Oo ooooO0O0 oOO0o0o0 oOO0o0o oOO0o0oO oOO0o0oo 0oOO0o oOO0oO00 oOO0oO0 oOO0oO0O oOO0oO0o oOO0oO oOO0oOO0 oOO0oOO oOO0oOOO oOO0oOOo 0oOO0oOo0 oOO0oOo oOO0oOoO oOO0oOoo oOO0oo00 oOO0oo0 oOO0oo0O oOO0oo0o oOO0oo oOO0ooO0 0oOO0ooO oOO0ooOO oOO0ooOo oOO0ooo0 oOO0ooo oOO0oooO oOO0oooo oOO oOOO000 oOOO000o 0oOOO0O oOOOoO oOOO00 oOOO00O oOOO00Oo oOOO00o0 oOOO00o oOOO00oO oOOO00oo oOOO0 0oOOO0oOO oOOO0O0 oOOO0O0o oOOO0OO0 oOOO0OO oOOO0OOO oOOO0OOo oOOO0Oo oOOO0OoO oOOO0Ooo 0oOOO0o00 oOOO0o0 oOOO0o0O oOOO0o0o oOOOOO oOOO0o oOOO0oO0 oOOO0oO oOOO0ooo oOOO0ooO 0oOOO0oOo oOOO0oo0 oOOO0oo oOOO oOOOO0OO oOOOO000 oOOOO00 oOOOoo00 oOOOO00O oOOOO00o 0oOOOO0 oOOOO0O0 oOOOO0O oOOOO0Oo oOOOO0o0 oOOOO0o oOOOO0oO oOOOO0oo oOo0o oOOOO 00oOOOOO00 0oOOOOO0 0oOOOOO0O 0oOOOOO0o 0oOOOOOO0 0oOOOOOO 0oOOOOOOO 0oOOOOOOo 0oOOOOOo0 0oOOOOOo 0oOOOOOoO oOOOOOoo oOOOOo00 oOOOOo0 oOOOOo0O oOOOOo0o oOOOOo oOOOOoO0 oOOOOoO oOOOOoOO 0oOOOOoOo oOOOOoo0 oOOOOoo oOOOOooO oOOOOooo oOOOo000 oOOOo00 oOOOo00O oOOOo00o oOOOo0 0oOOOo0O0 oOOOo0O oOOOo0OO oOOOo0Oo oOOOo0o0 oOOOo0o oOOOo0oO oOOOo0oo oOOOo oOOOoO00 0oOOOoO0 oOOOoO0O oOOOoO0o oOOOoOO0 oOOOoOO oOOOoOOO oOOOoOOo oOOOoOo0 oOOOoOo oOOOoOoO 0oOOOoOoo oOOOoo0 oOOOoo0O oOOOoo0o oOOOoo oOOOooO0 oOOOooO oOOOooOO oOOOooOo oOOOooo0 0oOOOooo oOOOoooO oOOOoooo oOOo0000 oOOo000 oOOo000O oOOo000o oOOo00 oOOo00O0 oOOo00O 0oOOo00OO oOOo00Oo oOOo00o0 oOOo00o oOOo00oO oOOo00oo oOOo0 oOOo0O00 oOOo0O0 oOOo0O0O 0oOOo0O0o oOOo0O oOOo0OO0 oOOo0OO oOOo0OOO oOOo0OOo oOOo0Oo0 oOOo0Oo oOOo0OoO oOOo0Ooo 0oOOo0o00 oOOo0o0 oOOo0o0O oOOo0o0o oOOo0o oOOo0oO0 oOOo0oO oOOo0oOO oOOo0oOo oOOo0oo0 00oOOo0oo 0oOOo0ooO 0oOOo0ooo 0oOOo 0oOOoO000 0oOOoO00 0oOOoO00O 0oOOoO00o 0oOOoO0 0oooO0oOO 0oOOoO0O0 oOOoO0O oOOoO0OO oOOoO0Oo oOOoO0o oOOoO0oO oOOoO0oo oOOoO oOOoOO0o oOOoOO00 0oOOoOO0 oOOoOO0O oOOoOOO oOOoOOOO oOOoOOOo oOOoOOo0 oOOoOOo oOOoOOoO oOOoOOoo oOOoOo00 0oOOoOo0 oOOoOo0O oOOoOo0o oOOoOo oOOoOoO0 oOOoOoO oOOoOoOo oOOoOoo0 oOOoOoo oOOoOooO 0oOOoOooo oOOoo000 oOOoo00 oOOoo00O oOOoo00o oOOoo0 oOOoo0O0 oOOoo0O oOOoo0OO oOOoo0Oo 0oOOoo0o0 oOOoo0o oOOoo0oO oOOoo0oo oOOoo oOOooO00 oOOooO0 oOOooO0O oOOooO0o oOOooO 0oOOooOO0 oOOooOO oOOooOOO oOOooOOo oOOooOo0 oOOooOo oOOooOoO oOOooOoo oOOooo00 oOOooo0 0oOOooo0O oOOooo0o oOOooo oOOoooO0 oOOoooO oOOoooOO oOOoooOo oOOoooo0 oOOoooo oOOooooO 0oOOooooo oOo0000 oOo000 oOo000O oOo000o oOo00O0 oOo00O oOo00OO oOo0o00 oOo00Oo 0oOo00o0 oOo00o oOo00oO oOo00oo oOo0 oOo0O000 oOo0O00 oOo0O00O oOo0oO0o oOo0O00o 000oOo0oo 00oOo0O0 00oOo0O0O0 00oOo0O0O 00oOo0O0OO 00oOo0O0Oo 00oOo0O0o0 00oOo0O0o 00oOo0O0oO 00oOo0O0oo 00oOo0O 0oOo0OO00 0oOoo00o 0oOo0OO0 0oOo0OO0O 0oOo0OO0o 0oOo0OO 0oOo0OOO0 0oOo0OOO 0oOo0OOOO 00oOo0OOOo 0oOo0OOo0 0oOo0OOo 0oOo0OOoO 0oOo0OOoo 0oOo0Oo00 0oOo0Oo0 0oOo0Oo0O 0oOo0Oo0o 0oOo0Oo 00oOo0OoO0 0oOo0OoO 0oOo0OoOO 0oOo0OoOo 0oOo0Ooo0 0oOo0Ooo 0oOo0OooO 0oOo0Oooo 0oOo0o000 0oOo0o00O 00oOo0o00o 0oOo0o0 0oOo0o0O 0oOo0o0OO 0oOo0o0Oo 0oOo0o0o0 0oOo0o0o 0oOo0oO00 0oOo0oO0 0oOo0oO0O 00oOo0oO 0oOo0oOO0 0oOo0oOO 0oOo0oOOO 0oOo0oOOo 0oOo0oOo0 0oOo0oOo 0oOo0oOoO 0oOo0oOoo 0oOo0oo00 00oOo0oo0 0oOo0oo0O 0oOo0ooO0 0oOo0ooO 0oOo0ooOO 0oOo0ooOo 0oOo0ooo0 0oOo0ooo 0oOo 0oOooOOoO 00oOoO0000 0oOoO000 0oOoO000O 0oOoO000o 0oOoO00 0oOoO00O0 0oOoO00O 0oOoO00OO 0oOoO00Oo 0oOoO00o0 00oOoO00o 0oOoO00oO 0oOoO00oo 0oOoO0 0oOooOo0O 0oOoO0O00 0oOoO0O0 0oOoO0O0O 0oOoO0O0o 0oOoO0o 00oOoO0O 0oOoO0OO0 0oOoO0OO 0oOoO0OOO 0oOoO0OOo 0oOoO0Oo0 0oOoO0Oo 0oOoO0OoO 0oOoO0Ooo 0oOooOo00 00oOoO0o00 0oOoO0o0 0oOoO0o0O 0oOoOoOOO 0oOoO0o0o 0oOoO0oO0 0oOoO0oO 0oOoO0oOO 0oOoO0oOo 0oOooOo0o 0oOoO0oo0 oOoO0oo oOoO0ooO oOoO0ooo oOoO oOoOO000 oOoOO00 oOoOO00O oOoOO00o oOoOO0 0oOoOO0O0 oOoOO0O oOoOOo0O oOoOO0OO oOoOO0Oo oOoOO0o0 oOoOO0o oOoOO0oO oOooOOOO oOoOO0oo 0oOoOO oOoOOO00 oOoOOO0 oOoOOO0O oOoOOO0o oOoOOO oOoOOOO0 oOoOOOO oOoOOOOO oOoOOOOo 0oOoOOOo0 oOoOOOo oOoOOOoO oOooOooO oOoOOOoo oOoOOo00 oOoOOo0 oOoOOo0o oOoOOo oOoOOoO0 0oOoOOoO oOoOOoOO oOoOOoOo oOoOOoo0 oOoOOoo oOoOOooO oOoOOooo oOoOo000 oOoOo00 oOoOo00O 0oOoOo00o oOoOo0 oOoOoo0O oOoOo0O0 oOoOo0O ooOOO0oo oOooo0Oo oOooo0oo oOoOo0OO ooOOO0o0 0oOoOo0Oo oOoOo0o0 oOoOo0o oOoOo0oO oOoOo0oo oOoOo ooOOOooo oOoOoO00 oOoOoO0 oOoOoO0O 0ooOOOooO oOooooOO oOoOoO0o oOoOoO oOoOoOO0 oOoOoOO oOoOoOOo oOoOoOo0 oOoOoOo oOooOOoo 0oOoOoOoO oOoOoOoo ooOOO0oO oOooo0oO oOoOoo00 oOoOoo0 ooOOO0O0 oOooo0O0 oOoOoo0o oOoOoo 00ooOOOo0o 0oOoooooo 0oOoOooO0 0oOoOooO 0oOoOooOO 0ooOOOo0O 0oOoooooO 0oOoOooOo 0oOoOooo0 0oOoOooo 0ooOOOo00 oOooooo0 oOoOoooO oOoOoooo oOoo0000 oOoo000 oOoo000O oOoo000o oOoo00 oOoo00O0 0oOoo00O oOoo00OO oOoo00Oo oOoo00o0 oOoo00oO oOoo00oo oOoo0Oo0 oOoo0O00 oOoo0O0 oOoo0O0O 0oOoo0O0o oOoo0O oOoo0OO0 oOoo0oO oOooo00 oOoo0OO oOoo0OOO oOoo0OOo oOoo0Oo oOoo0OoO 0oOoo0Ooo oOoo0o00 oOoo0o0 oOoo0o0O oOoo0o0o oOoo0o oOoo0oO0 oOoo0oOO oOoo0oOo oOoo0oo0 0oOoo0oo oOoo0ooO oOoo0ooo oOoo oOooO000 oOooO00 oOooO00O oOooO00o oOooO0 oOooO0O0 0oOooO0O oOooO0OO oOooO0Oo oOooO0o0 oOooO0o oOooO0oO oOooO0oo oOooO oOooOO00 oOooOO0 0oOooOOo0 oOooOO0O oOooOO0o oOooOO oOooOOO0 oOooOOO oOooOOOo oOooOOo oOooOo0 oOooOo 0oOooOoO0 oOooOoO oOooOoOO oOooOoOo oOooOoo0 oOooOoo oOooOooo oOooo000 oOooo00O oOooo00o 0oOoooO oOooo0 oOooo0O oOooo0OO oOooo0o0 oOoooO00 oOoooO0 oOoooO0O oOoooO0o oOoooOO0 00oOoooOO 0oOoooOOO 0oOoooOOo 0oOoooOo0 0oOoooOo 0oOoooOoO 0oOoooOoo 0oOoooo00 0oOoooo0 0oOoooo0O 0oOoooo0o oOoooo oOooooO0 oOooooO oOooooOo oOooooo oo000000 oo00000 oo00000O oo00000o 0oo0000 oo0000O0 oo0000O oo0000OO oo0000Oo oo0000o0 oo0000o oo0000oO oo0000oo oo000 0oo000O00 oo000O0 oo000O0O oo000O0o oo000O oo000OO0 oo0OOOO oo000OO oo000OOO oo000OOo 0oo000Oo0 oo000Oo oo000OoO oo000Ooo oo000o00 oo000o0 oo000o0O oo000o0o oo000oO0 oo000oO 0oo000oOO oo000oOo oo000oo0 oo000oo oo000ooO oo00 oo00O00o oo00O000 oo00O00 oo00O00O 0oo00O0 oo00O0O0 oo00O0O oo00Oo0O oo00O0OO oo00O0Oo oo00O0o0 oo00O0o oo00O0oO oo00O0oo 0oo00O oo00OO00 oo00OO0 oo00OO0O oo00OO0o oo00OO oo00OOO0 oo00OOO oo00OOOO oo00OOOo 0oo00OOo0 oo00OOo oo00OOoO oo00OOoo oo00Oo00 oo00Oo0 oo00Oo0o oo00Oo oo00OoO0 oo00OoO 0oo00OoOO oo00OoOo oo00Ooo0 oo00Ooo oo00OooO oo00Oooo oo00o000 oo00o00 oo00o0o0 oo00o00O 00oo00o00o 0oo00o0 0oo00o0oo 0oo00ooOO 0oo00o0O0 0oo00o0O 0oo00o0OO 0oo00o0Oo 0oo00o0o 0oo00o0oO 0oo00oO00 oo00oO0 oo00oO0O oo00oO0o oo00oOoO oo00oOO0 oo00oOo oo00oOO oo00oOOO oo00oOOo 0oo00oOo0 oo00oOoo oo00oo00 oo00oo0 oo00oo0O oo00oo0o oo00oo oo00ooO0 oo00ooO oo00ooOo 0oo00ooo0 oo00ooo oo00oooO oo00oooo oo0 oo0O0000 oo0O000 oo0O000O oo0O000o oo0O00 0oo0oOOOO oo0O00O0 oo0O00O oo0O00OO oo0O00Oo oo0O00o0 oo0O00o oo0O00oO oo0O00oo oo0O0 0oo0O0O00 oo0O0O0 oo0O0O0O oo0O0O0o oo0O0O oo0O0OO0 oo0O0OO oo0O0OOO oo0O0OOo oo0O0Oo0 0oo0O0Oo oo0O0OoO oo0O0Ooo oo0O0o00 oo0O0o0 oo0O0o0O oo0O0o0o oo0O0o oo0O0oO0 ooo0OoO 0oo0O0oO oo0oOOoO oo0O0oOO oo0O0oOo oo0O0oo0 oo0O0oo oo0O0ooO oo0O0ooo oo0OoOO0 oo0OO00o 0oo0OO00O oo0OO000 oo0OO00 oo0Oo0 oo0Ooo oo0OoO oo0OO0 oo0OOoOO oo0OO0Oo oo0OOo0O 0oo0OOooO oo0OO0O0 oo0OO0O oo0OO0OO oo0OO0o0 oo0OO0o oo0OO0oO oo0OO0oo oo0OO oo0OOO00 00oo0oOoo 0oo0OOO0 0oo0OOO0O 0ooo000O0 0oo0OOO0o 0oo0OOO 0ooo000o0 0oo0OOOO0 0oo0OOOOO 0oo0OOOOo 0oo0OOOo0 oo0OOOo oo0OOOoO ooo0000O ooo00000 oo0OOOoo oo0OOo00 oo0OOo0 oo0OOo0o oo0OOo 0oo0OOoO0 oo0OOoO oo0OOoOo oo0OOoo0 oo0OOooo oo0Oo000 oo0Oo00 oo0Oo00O oo0Oo00o oo0Oo0O0 0oo0Oo0O oo0Oo0OO oo0Oo0Oo oo0Oo0o0 oo0Oo0o oo0Oo0oO oo0Oo0oo oo0Oo oo0OoO00 oo0OoO0 0oo0OoO0O oo0OoO0o oo0OoOO oo0OoOOO oo0OoOOo oo0OoOo0 oo0OoOo oo0OoOoO oo0OoOoo oo0Ooo00 0oo0Ooo0 oo0Ooo0O oo0Ooo0o oo0OooO oo0OooOO oo0OooOo oo0Oooo0 oo0Oooo oo0OoooO 0oo0Ooooo oo0o0000 oo0o000 oo0o000O oo0o000o oo0o00 oo0o00O0 oo0o00o oo0o00O oo0o00Oo 0oo0o00oO oo0o00OO oo0o00o0 oo0o00oo oo0o0 oo0o0O00 oo0o0O0o oo0o0o oo0o0O oo0o0OO0 0oo0o0OO oo0o0OOO oo0o0OOo oo0o0Oo0 oo0o0OoO oo0o0Ooo oo0o0o00 oo0o0o0 oo0o0o0O oo0o0o0o 0oo0o0oO0 oo0o0oO oo0o0oOO oo0o0oOo oo0o0oo0 oo0o0oo oo0o0ooO oo0o0ooo oo0o oo0oO000 00oo0oO00 0oo0oO0oO 0oo0oO00O 0oo0oO00o 0oo0oO0O0 0oo0oO0O 0oo0oO0OO 0oo0oO0Oo 0oo0oO0o0 0oo0oO0o 0oo0oO0oo oo0oO oo0oOO00 oo0oOO0O oo0oOO0o oo0oOO oo0oOOO0 oo0oOOO oo0oOOOo oo0oOOo0 0oo0oOOoo oo0oOo00 oo0oOo0 oo0oOo0O oo0oOo0o oo0oOo oo0oOoO0 oo0oOoOO oo0oOoOo oo0oOoo0 0oo0oOooO oo0oOooo oo0oo000 ooo0oOO oooOooO oo0oo00 oo0oo00O oo0oo00o oo0oo0 oo0oo0O0 0oo0oo0O oo0oo0OO oo0oo0Oo oo0oo0o0 oo0oo0o oo0oo0oO oo0oo0oo oo0oo oo0ooO00 oo0ooO0 0oo0ooO0O oo0ooO0o oo0ooOO0 oo0ooOO ooo0O0oo ooo0oooO oo0ooOOO oo0ooOOo oo0ooOo0 oo0ooOo 0oo0ooOoO oo0ooOoo oo0ooo00 oo0ooo0 oo0ooo0o oo0ooo0O oo0ooo oo0oooOO oo0oooO0 oo0oooO 0oo0oooOo oo0oooo0 oo0oooo oo0ooooO oo0ooooo oo ooO00000 oooooOo ooO0000 ooO0000O 0ooOooOOO ooO0000o ooO0oo ooO000 ooO000O0 ooO000O ooO000OO ooO000Oo ooO000o0 ooO000o 0ooO000oO ooO000oo ooO00 ooO0OOoo ooOo000o ooOo00O0 ooO00O00 ooO00O0O ooO0OOoO ooO00O0o 00ooO00O 0ooOo00o0 0ooO00OO0 0ooO00OO 0ooO0OOOO 0ooO00OOO 0ooO00OOo 0ooO00Oo0 0ooO00Oo 0ooO00OoO 0ooOo00OO ooO00Ooo ooO00o00 ooO00o0 ooO00o0O ooO00o0o ooO00o ooO00oO0 ooO00oO ooO00oOO 0ooO00oOo ooO00oo0 ooO00oo ooO00ooO ooO00ooo ooO0 ooO0O000 oooo000 ooO0O00 ooO0O00O 0ooO0O00o ooO0O0 ooO0O0O0 ooO0O0O ooO0O0OO ooO0O0Oo ooO0O0o0 ooO0OOO ooO0O0o ooO0O0oO 0ooO0O0oo ooO0O ooOo000O ooO0OO00 ooO0OO0 ooO0OO0O ooO0OO0o ooO0OO ooO0OOO0 ooO0OOOo 0ooO0OOo0 ooO0OOo ooO0Oo00 ooo0oOo ooO0Oo0 ooO0Oo0O ooO0Oo0o ooO0Oo ooO0OoO0 ooO0OoO 0ooO0OoOO ooO0OoOo ooO0Ooo0 ooO0OooO ooO0Oooo ooO0o000 ooO0o00 ooO0o00O ooO0o00o ooO0o0 0ooO0o0O0 ooO0o0O ooO0o0OO ooO0o0Oo ooO0o0o0 ooO0o0o ooO0o0oO ooO0o0oo ooO0o ooO0oO00 0ooO0oO0 ooO0oO0O ooOo00Oo ooO0oO0o ooO0oO ooO0oOO0 ooO0oOO ooO0oOOO ooO0oOOo ooO0oOo0 0ooo0OOo ooO0oOo ooO0oOoO ooO0oOoo ooO0oo00 ooO0oo0 ooO0oo0O ooO0oo0o ooO0ooO0 ooO0ooO 00ooO0ooOO 0ooO0ooOo 0ooO0ooo0 0ooO0ooo 0ooO0oooO 0ooO0oooo 0ooo 0ooO 0ooOO0000 0ooOO000 0ooOO000O ooOO000o ooOO00 ooOO00O0 ooOO00O ooOO00OO ooOO00Oo ooOO00o0 ooOO00o ooOO00oO 0ooOO00oo ooOO0 ooOO0O00 ooOO0O0 ooOO0O0O ooOO0O0o ooOO0OO0 ooOO0OO ooOO0OOO ooOOo0OO 0ooOO0OOo ooOO0Oo0 ooOO0Oo ooOO0OoO ooOO0Ooo ooOO0o00 ooOO0o0 ooOO0o0O ooOO0o0o ooOO0o 0ooOO0oO0 ooOO0oO ooOO0oOO ooOO0oOo ooOO0oo0 ooOO0oo ooOO0ooO ooOO0ooo ooOOO00 ooOOoO 0ooOOO0 ooOOO0O ooOOO0o ooOOO ooOOOO00 ooOOOO0 ooOOOO0O ooOOOO0o ooOOOO ooOOOOO0 0ooOOOOO ooOOOOOO ooOOOOo ooOOOo0 ooOOOo ooOOOoO ooOOOoo ooOOo000 ooOOo00O ooOOo00o 0ooOOo0O0 ooOOo0O ooOOo0Oo ooOOo0o0 ooOOo0o ooOOo0oO ooOOo0oo ooOOo ooOOoO0 ooOOoO0O 0ooOOoO0o ooOOoOo ooOOoo00 ooOOoo0 ooOOoo0O ooOOoo0o ooOOoo ooOOooO0 ooOOooO ooOOooOO 0ooOOooo0 ooOOooo ooOOoooo ooOo0000 ooOo000 ooOo00 ooOo00oO ooOo00oo ooOo0 ooOo0O00 00ooOo0o0 0ooOo0O0 0ooOo0oOo 0ooOo0O0O 0ooOo0O0o 0ooOo0O 0ooOo0OO0 0ooOo0OO 0ooOoOo0o 0ooOooOOo 0ooOo0OOO ooOo0OOo ooOo0Oo0 ooOo0Oo ooOo0OoO ooOo0Ooo ooOo0o00 ooOo0o0O ooOo0o0o ooOo0o 0ooOo0oO0 ooOo0oO ooOo0oOO ooOo0oo0 ooOo0oo ooOo0ooO ooOo0ooo ooOoO000 ooOoO00 ooOoO00O 0ooOoO00o ooOoO0 ooOoO0O0 ooOoO0O ooOoO0OO ooOoO0Oo ooOoO0o0 ooOoO0o ooOoO0oO ooOoO0oo 0ooOoO ooOoOoOO ooOoOO00 ooOoOO0 ooOoOOOo ooOoOO0O ooOoOO0o ooOoOO ooOoOOO0 ooOoOOO 0ooOoOOOO ooOoOOo0 ooOoOOo ooOoOOoO ooOoOOoo ooOoOo00 ooOoOo0 ooOoOo0O ooOoOo ooOoOoO0 0ooOoOoO ooOoOoOo ooOoOoo0 ooOoOoo ooOoOooO ooOoOooo ooOoo000 ooOoo00 ooOooo0o ooOoo00O 0ooOoo00o ooOoo0 ooOoo0O0 ooOoo0O ooOoo0OO ooOoo0Oo ooOoo0o0 ooOoo0o ooOoo0oo ooOoo0oO 0ooooO ooOoo ooOooO00 ooOooO0 ooOooO0O ooOooO0o ooOooo ooOooO ooOooOO0 ooOooOO 0ooOooOo0 ooOooOo ooOooOoO ooOooOoo ooOooo00 ooOooo0 ooOooo0O ooOoooO0 ooOoooO ooOoooOO 000ooOoooOo 00ooOoooo0 00ooOoooo 00ooOooooO 00ooOooooo 00ooo0000 00ooo000oo 00ooo0000o 00ooo000 00ooo000O 00ooo000OO 0ooo000Oo 0ooo000o 0ooo000oO 0ooo00 0ooo00O00 0ooo00oO0 0ooo00O0O 0ooo00O0o 0ooo00O 00ooo00Oo0 0ooo00OO0 0ooo00OO 0ooo00OOO 0ooo00OOo 0ooo00Oo 0ooo00OoO 0ooo00Ooo 0ooo00o00 0ooo00o0 00ooo00o0O 0ooo00o0o 0ooo00o 0ooo00oO 0ooo00oOO 0ooo00oOo 0ooo00oo0 0ooo00oo 0ooo00ooO 0ooo00ooo 00ooo0 0ooo0O000 0ooo0O00 0ooo0O00O 0ooo0O00o 0ooo0oo 0ooo0o0 0ooo0oO 0ooo0O0 0ooo0O0O0 00ooo0O0O 0ooo0O0OO 0ooo0O0Oo 0ooo0O0o0 0ooo0O0o 0ooo0O0oO 0ooo0O 0ooo0OO00 0ooo0OO0 0ooo0OO0O 00ooo0OO0o 0ooo0Oo 0ooo0OO 0ooo0OOO0 0ooo0OOO 0oooo00oo 0ooo0OOoO 0ooo0OOOO 0ooo0OOOo 0ooo0OOo0 00ooo0OOoo 0ooo0Oo00 0ooo0Oo0O 0ooo0Oo0o 0ooo0OoO0 0ooo0OoOO 0ooo0OoOo 0ooo0Ooo0 0ooo0OooO 0ooo0Oooo 00ooo0o000 0ooo0o00 0ooo0o00O 0ooo0o00o 0ooo0o0OO 0ooo0o0O0 0ooo0o0O 0ooo0o0Oo 0ooo0o0o0 0ooo0o0o 00ooo0o0oO 0ooo0o0oo 0ooo0oO00 0ooo0oO0 0ooo0oO0O 0ooo0oO0o 0ooo0oOO0 0ooo0oOOO 0ooo0oOOo 0ooo0oOo0 00ooo0oOoO 0ooo0oOoo 0ooo0oo00 0ooo0oo0 0ooo0oo0O 0ooo0oo0o 0ooo0ooO0 0ooo0ooO 0ooo0ooOO 0ooo0ooOo 0ooo0ooo0 ooo0oooo oooO0oo0 oooO0000 oooO000 oooO00o0 oooO000O oooO0ooo oooO000o ooooo0 0oooooo ooooOo oooO00 oooO00O0 oooO00O oooO00Oo oooO00OO oooO00o ooooOOOo ooooOOOO 0ooooOo00 oooO0oO0 oooO00oO oooO00oo oooO0 oooO0O00 oooO0O0 oooO0O0O oooO0O0o oooO0O 0oooOOo0O oooO0OO0 oooO0OO oooO0OOO oooO0OOo oooO0Oo0 oooO0Oo oooO0OoO oooO0Ooo oooO0o00 0oooO0o0 oooO0o0O oooO0o0o oooooO oooO0o oooO0oO oooO0oo oooO0ooO oooO oooOooOO 0oooOO000 oooOO00 oooOO0o0 oooOO00O oooOO00o oooOO0O0 oooOO0O oooOO0OO oooOO0Oo oooOO0o 0oooOO0oO oooOO0oo oooOO oooOOO00 oooOOO0 oooOOO0O oooOOO0o oooOOO oooOOOO0 oooOOOO 0oooOOOOO oooOOOOo oooOOOo0 oooOOOo oooOOOoO oooOOOoo oooOOo00 oooOOo0 oooOOo0o oooOOo 0oooOOoO0 oooOOoO oooOOoOO oooOOoOo oooOOoo0 oooOOoo oooOOooO oooOOooo oooOo000 oooOo00 00oooOo00O 0oooOo00o 0oooOo0 0oooOo0oo 0oooOo0O0 0oooOo0O 0oooOo0OO 0oooOo0Oo 0oooOo0o0 0oooOo0o 0oooOo0oO oooOo oooOoO00 oooOoO0 oooOoO0O oooOoO0o oooOoOOO oooOoOO0 oooOoOO oooOoOOo 0oooOoOo0 oooOoOo oooOoOoO oooOoOoo oooOoo00 oooOoo0 oooOoo0O oooOoo0o oooOooO0 oooOooOo 0oooOooo0 oooOooo oooOoooO oooOoooo oooo0000 oooo000O oooo000o oooo00 oooo00o0 oooo00O0 0oooo00O oooo00OO oooo00Oo oooo00oO oooo0 oooo0O00 oooo0O0 oooo0O0O oooo0O0o oooo0O 0oooo0OO0 oooo0OO oooo0OOO oooo0OOo oooo0Oo0 oooo0Oo oooo0OoO oooo0Ooo oooo0o00 oooo0o0 0oooo0o0O oooo0o0o oooo0o oooo0oO0 oooo0oO oooo0oOO oooo0oOo oooo0oo0 oooo0oo oooo0ooO 0oooo0ooo oooo ooooO00 ooooOOoO ooooO00O ooooO00o ooooO0 ooooO0O ooooO0OO ooooO0Oo 0ooooO0o0 ooooO0o ooooO0oO ooooOO0 ooooOO0o ooooOO ooooOoo0 ooooOOO0 ooooOOO ooooOOo 0ooooOo0 ooooOo0O ooooOo0o ooooOoO0 ooooOoO ooooOoo ooooOooO ooooOooo ooooo000 ooooo00 00ooooo00O 0ooooo00o 0ooooo0O0 0ooooo0O 0ooooo0OO 0ooooo0Oo 0ooooo0o0 0ooooo0o 0ooooo0oO 0ooooo0oo 0ooooo oooooO00 oooooO0 oooooOo0 oooooO0O oooooO0o oooooOO0 oooooOO oooooOOO oooooOOo 0oooooOoO oooooOoo oooooo00 oooooo0 oooooo0O oooooo0o ooooooO0 ooooooOO ooooooOo ooooooo0 0oooooooO oooooooo O O0 O00 O000 O0000 O00000 O000000 O0000000 O000000O O00000O O00000O0 O00000OO O0000O O0000O0 O0000O00 O0000O0O O0000OO O0000OO0 O0000OOO O000O O000O0 O000O00 O000O000 O000O00O O000O0O O000O0O0 O000o0oO O000Oo O000OO0 O000oo00 O000OO0O O000OOO O000OOO0 O000OOOO O00O O00O0 O00O00 O00O000 O00O0000 O00O000O O00O00O O00O00O0 O00O00OO O00O0O O00O0O0 O00O0O00 O00O0O0O O00O0oO O00O0OO0 O00O0OOO O00OO O00OO0 O00OO00 O00Oo000 O00Oo00O O00Oo0O O00Oo0O0 O00oo0oO O00OOO O00OOO0 O00OoO00 O00ooo0O O00OOOO O00oOoO0 O00ooooO O0O O0O0 O0O00 O0O000 O0O0000 o0o00000 o0o0000O O0O000O o0O000O0 o0O000OO O0O00O O0O00O0 o0O00O00 o0O00O0O O0O00oo o0O00OO0 o0O00OOo O0o0o O0O0O0 O0O0O00 o0O0O000 o0O0O00o O0O0O0O o0O0O0O0 o0O0O0OO O0O0Oo O0o0oo0 o0O0OO00 o0O0OO0o O0o0ooo o0O0OOo0 o0O0OOOO O0OO O0OO0 O0OO00 O0OO000 o0OO0000 o0OO000O o0Oo00O o0OO00O0 o0OO00oO O0OO0o O0OO0O0 o0OO0O00 o0oO0O0O O0OO0OO o0oO0Oo0 o0oO0oOo O0OOO O0OOo0 o0OoO00 o0OOO000 o0OoO00o O0OoO0o o0ooo0O0 o0ooo0Oo O0oOOO O0OOOO0 o0ooOO00 o0OOOO0O O0oOOOO o0ooOOo0 o0ooooOO OO OO0 OO00 OO000 Oo0000 OO00000 oO000000 oO00000O OO0000O oO0000O0 oO0000OO OO000O OO000O0 oO000O00 oO000o0O oO000OO oO000OO0 oo000ooo OO00o OO00o0 OO00O00 oO00O000 oO00O00O OO00O0O oO00O0O0 oO00O0OO Oo00oO OO00OO0 oO00OO00 oO00OO0o Oo00oOo oO00OOO0 oO00OOOO OO0O OO0O0 OO0O00 OO0O000 oO0O0000 oO0O000O OO0O00O oO0O00O0 oO0O00OO OO0o0O OO0O0O0 oO0O0o00 oo0o0O0O Oo0o0OO oO0O0OO0 oO0O0Ooo OO0Oo OO0OO0 OO0OO00 oO0Oo000 oO0Oo00o OO0OO0O oO0OO0O0 oO0Oo0oO Oo0OOO OO0OOO0 oO0OOo00 oO0OoO0o Oo0OoOO oO0Oooo0 oO0OoOOo OOo OOO0 OoO00 OOO000 OOO0000 oOo00000 oOo0000o OOO000O oOo000O0 oOo000oO OOO00O ooo00O0 oOo00O00 oOo00O0o OOO00OO oOO00oo0 oOo00Ooo OOo0O OOO0O0 OOO0O00 oOO0o000 oOO0o00O Ooo0o0O oOo0o0O0 oOo0o0oo OOO0OO Ooo0Oo0 oOO0OO00 oOo0oo0o ooo0ooo oOO0OOO0 oOo0oooo OOOO OooO0 OOOO00 OOOO000 oOOO0000 oOOO000O ooOo00o oOOO00O0 oOOO00OO OOOO0o OOOO0O0 oOOO0O00 oOOO0O0O Oooo0Oo oOOO0Oo0 oooO0oOo Ooooo OOoOO0 OoOOO00 ooOOO000 ooOOO00o OOOOO0O oOOoO0o0 ooOOO0OO oooOoo OOOOOO0 ooOOoO00 ooooOO0O ooOOoOO ooOOOOo0 ooOOOoOO ================================================ FILE: app/proguard-log.pro ================================================ ########################################################################################################## # 作者:Sollyu # 日期:2020-11-02 # 内容:发布版本移除日志,kotlin编译时带的而外信息,增强反调试难度 # 使用:proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro', 'proguard-log.pro' ########################################################################################################## ########################################################################################################## # 删除安卓日志 -assumenosideeffects class android.util.Log { public static *** d(...); public static *** v(...); public static *** w(...); public static *** e(...); } ########################################################################################################## # 删除Kotlin编译时可能生成显示变量的方法 -assumenosideeffects class kotlin.jvm.internal.Intrinsics { public static void checkExpressionValueIsNotNull(java.lang.Object, java.lang.String); public static void checkFieldIsNotNull(java.lang.Object, java.lang.String); public static void checkFieldIsNotNull(java.lang.Object, java.lang.String, java.lang.String); public static void checkNotNull(java.lang.Object); public static void checkNotNull(java.lang.Object, java.lang.String); public static void checkNotNullExpressionValue(java.lang.Object, java.lang.String); public static void checkNotNullParameter(java.lang.Object, java.lang.String); public static void checkParameterIsNotNull(java.lang.Object, java.lang.String); public static void checkReturnedValueIsNotNull(java.lang.Object, java.lang.String); public static void throwUninitializedPropertyAccessException(java.lang.String); } ########################################################################################################## # 会暴露变量名称 -assumenosideeffects class java.util.Objects { public static java.lang.Object requireNonNull(java.lang.Object, java.lang.String); } ########################################################################################################## # 删除slf4j的日志输出 -assumenosideeffects interface org.slf4j.Logger { public void trace(...); public void debug(...); public void info(...); public void warn(...); public void error(...); public boolean isTraceEnabled(...); public boolean isDebugEnabled(...); public boolean isWarnEnabled(...); } -assumenosideeffects class org.slf4j.LoggerFactory { public static ** getLogger(...); } ================================================ FILE: app/proguard-rules.pro ================================================ -keep class com.sevtinge.cemiuiler.XposedInit -keep class com.sevtinge.cemiuiler.module.app.SystemFrameworkForCorePatch -keep class moralnorm.**{*;} -keep class com.sevtinge.cemiuiler.utils.Helpers{boolean isModuleActive;} -keep class com.sevtinge.cemiuiler.utils.Helpers{int XposedVersion;} -keep class * extends com.sevtinge.cemiuiler.module.base.BaseHook -keep class com.sevtinge.cemiuiler.ui.HideAppActivity -keep class * extends com.sevtinge.cemiuiler.ui.fragment.base.* -keep class miui.drm.**{*;} -dontwarn android.app.ActivityTaskManager$RootTaskInfo -dontwarn miui.app.MiuiFreeFormManager$MiuiFreeFormStackInfo -dontwarn com.android.internal.view.menu.MenuBuilder -allowaccessmodification -overloadaggressively ================================================ FILE: app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: app/src/main/assets/xposed_init ================================================ com.sevtinge.cemiuiler.XposedInit ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/Application.java ================================================ package com.sevtinge.cemiuiler; import android.content.Context; import android.os.Build; import com.sevtinge.cemiuiler.utils.PrefsUtils; public class Application extends android.app.Application { @Override protected void attachBaseContext(Context base) { PrefsUtils.mSharedPreferences = PrefsUtils.getSharedPrefs(base); super.attachBaseContext(base); } @Override public void onCreate() { super.onCreate(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/CrashRecord.kt ================================================ package com.sevtinge.cemiuiler import android.annotation.SuppressLint import android.content.Context import com.sevtinge.cemiuiler.utils.PrefsUtils.mPrefsName import de.robv.android.xposed.XposedBridge @SuppressLint("StaticFieldLeak") object CrashRecord : Thread.UncaughtExceptionHandler { private var mDefaultHandler: Thread.UncaughtExceptionHandler? = null private var mContext: Context? = null fun init(context: Context) { mContext = context mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler() Thread.setDefaultUncaughtExceptionHandler(this) if (BuildConfig.DEBUG) XposedBridge.log("[Cemiuiler][I]: CrashRecord Loaded") } override fun uncaughtException(p0: Thread, p1: Throwable) { XposedBridge.log("[Cemiuiler][W]: Crash happened") mContext?.let { val pref = it.createDeviceProtectedStorageContext().getSharedPreferences("Crash_Handler", Context.MODE_PRIVATE) if (BuildConfig.DEBUG) { XposedBridge.log("${System.currentTimeMillis()}") XposedBridge.log("${pref.getLong("last_time", 0L)}") XposedBridge.log("${System.currentTimeMillis() - pref.getLong("last_time", 0L)}") } if (System.currentTimeMillis() - pref.getLong("last_time", 0L) < 60 * 1000L) { XposedBridge.log("[Cemiuiler][W]: Crash happened again in one minute") if (pref.getInt("times", 0) >= 5) { it.createDeviceProtectedStorageContext().getSharedPreferences(mPrefsName, Context.MODE_PRIVATE).edit().apply { clear() apply() } XposedBridge.log("[Cemiuiler][W]: More than five times, clear MODULE_CONFIG") pref.edit().putInt("times", 0).apply() } pref.edit().putInt("times", pref.getInt("times", 0) + 1).apply() } pref.edit().putLong("last_time", System.currentTimeMillis()).apply() Thread.sleep(500) } mDefaultHandler?.uncaughtException(p0, p1) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/XposedInit.kt ================================================ package com.sevtinge.cemiuiler import com.github.kyuubiran.ezxhelper.EzXHelper import com.sevtinge.cemiuiler.module.app.SystemFrameworkForCorePatch import com.sevtinge.cemiuiler.module.base.BaseXposedInit import com.sevtinge.cemiuiler.module.hook.home.title.EnableIconMonetColor import com.sevtinge.cemiuiler.module.hook.securitycenter.SidebarLineCustom import com.sevtinge.cemiuiler.module.hook.settings.VolumeSeparateControlForSettings import com.sevtinge.cemiuiler.module.hook.systemframework.* import com.sevtinge.cemiuiler.module.hook.systemui.navigation.HandleLineCustom import com.sevtinge.cemiuiler.module.hook.tsmclient.AutoNfc import de.robv.android.xposed.IXposedHookInitPackageResources import de.robv.android.xposed.IXposedHookZygoteInit import de.robv.android.xposed.callbacks.XC_InitPackageResources import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam private const val TAG = "Cemiuiler" class XposedInit : BaseXposedInit(), IXposedHookInitPackageResources { @Throws(Throwable::class) override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam?) { super.initZygote(startupParam) if (mPrefsMap.getBoolean("system_framework_allow_uninstall")) AllowUninstall().initZygote(startupParam) if (mPrefsMap.getBoolean("system_framework_screen_all_rotations")) ScreenRotation.initRes() if (mPrefsMap.getBoolean("system_framework_clean_share_menu")) CleanShareMenu.initRes() if (mPrefsMap.getBoolean("system_framework_clean_open_menu")) CleanOpenMenu.initRes() if (mPrefsMap.getBoolean("system_framework_volume_separate_control")) VolumeSeparateControlForSettings.initRes() // if (mPrefsMap.getBoolean("various_theme_crack")) ThemeCrack.initRes() if (startupParam != null) { BackgroundBlurDrawable().initZygote(startupParam) SystemFrameworkForCorePatch().initZygote(startupParam) } } @Throws(Throwable::class) override fun handleLoadPackage(lpparam: LoadPackageParam) { // Init EzXHelper EzXHelper.apply { initHandleLoadPackage(lpparam) setLogTag(TAG) setToastTag(TAG) } init(lpparam) SystemFrameworkForCorePatch().handleLoadPackage(lpparam) } override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) { when (resparam.packageName) { "com.miui.tsmclient" -> if (mPrefsMap.getBoolean("tsmclient_auto_nfc")) { AutoNfc.initResource(resparam) } "com.miui.home" -> if (mPrefsMap.getBoolean("home_other_icon_monet_color")) { EnableIconMonetColor.initResource(resparam) } "com.miui.securitycenter" -> if (mPrefsMap.getBoolean("security_center_sidebar_line_color")) { SidebarLineCustom.initResource(resparam) } "com.android.systemui" -> if (mPrefsMap.getBoolean("system_ui_navigation_handle_custom")) { HandleLineCustom.initResource(resparam) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/callback/IAppSelectCallback.java ================================================ package com.sevtinge.cemiuiler.callback; public interface IAppSelectCallback { void sendMsgToActivity(byte[] appIcon, String appName, String appPackageName, String appVersion, String appActivityName); String getMsgFromActivity(String s); } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/data/AppData.java ================================================ package com.sevtinge.cemiuiler.data; import android.graphics.Bitmap; public class AppData { public int user = 0; public Bitmap icon; public String label; public String packageName; public String activityName; public String versionName; public String versionCode; public boolean isSystemApp; public boolean enabled; } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/data/LocationData.java ================================================ package com.sevtinge.cemiuiler.data; public class LocationData { private String Title; // 备注 private Double Longitude; // 经度 private Double Latitude; // 纬度 private int Offset; private int RegionCode; // 区域代码 private int BaseStationCode; // 基站代码 private int f; private String Remarks; // 备注 public LocationData() { } // 标题,经度,纬度,偏移 public LocationData(String title, Double longitude, Double latitude, int offset, int regionCode, int baseStationCode, String remarks, int i4) { Title = title; Longitude = longitude; Latitude = latitude; Offset = offset; RegionCode = regionCode; BaseStationCode = baseStationCode; Remarks = remarks; f = i4; } public String getTitle() { return Title; } public void setTitle(String title) { Title = title; } public Double getLongitude() { return Longitude; } public void setLongitude(Double longitude) { Longitude = longitude; } public Double getLatitude() { return Latitude; } public void setLatitude(Double latitude) { Latitude = latitude; } public int getOffset() { return Offset; } public void setOffset(int offset) { Offset = offset; } public int getRegionCode() { return RegionCode; } public void setRegionCode(int regionCode) { RegionCode = regionCode; } public int getBaseStationCode() { return BaseStationCode; } public void setBaseStationCode(int baseStationCode) { BaseStationCode = baseStationCode; } public int getF() { return f; } public void setF(int f) { this.f = f; } public String getRemarks() { return Remarks; } public void setRemarks(String remarks) { Remarks = remarks; } public String toString() { return String.valueOf(Latitude) + "," + String.valueOf(Longitude) + "," + String.valueOf(Offset) + "," + String.valueOf(RegionCode) + "," + String.valueOf(BaseStationCode) + "," + Remarks; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/data/ModData.java ================================================ package com.sevtinge.cemiuiler.data; public class ModData { public String title; public String breadcrumbs; public String key; public ModCat cat; public String sub; public int order; public String fragment; public int catTitleResId; public enum ModCat { pref_key_system, pref_key_launcher, pref_key_controls, pref_key_various } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/data/SQLiteHelper.java ================================================ package com.sevtinge.cemiuiler.data; import android.content.ContentValues; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteException; import android.database.sqlite.SQLiteOpenHelper; import androidx.annotation.Nullable; import com.sevtinge.cemiuiler.utils.ToastHelper; import java.io.File; public class SQLiteHelper extends SQLiteOpenHelper { public static SQLiteDatabase a = null; public SQLiteHelper(@Nullable Context context) { super(context, a(context), null, 1); try { a = getWritableDatabase(); a.execSQL("create table if not exists location(id integer primary key autoincrement,title text,lng real,lat real,offset integer,lac integer,cid integer,note text)"); } catch (SQLiteException e) { ToastHelper.makeText(context, e.getMessage()); } } private static String a(Context context) { String str = context.getExternalFilesDir(null) + "/location.db"; return new File(str).exists() ? str : "location.db"; } public int a(LocationData data) { return a.delete("location", "id = ?", new String[]{String.valueOf(data.getF())}); } public long b(LocationData data) { ContentValues contentValues = new ContentValues(); contentValues.put("title", data.getTitle()); contentValues.put("lat", data.getLatitude()); contentValues.put("lng", data.getLongitude()); contentValues.put("offset", data.getOffset()); contentValues.put("lac", data.getBaseStationCode()); contentValues.put("cid", data.getRegionCode()); contentValues.put("note", data.getRemarks()); return a.insert("location", null, contentValues); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table if not exists location(id integer primary key autoincrement,title text,lng real,lat real,offset integer,lac integer,cid integer,note text)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/data/adapter/AppDataAdapter.java ================================================ package com.sevtinge.cemiuiler.data.adapter; import android.annotation.SuppressLint; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.data.AppData; import com.sevtinge.cemiuiler.utils.PrefsUtils; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; public class AppDataAdapter extends RecyclerView.Adapter { private static List appInfoList; private Set selectedApps; private onItemClickListener onItemClickListener; private final Context mContext; private final String mKey; private final int mType; @SuppressLint("NotifyDataSetChanged") public void setData(List appInfoList) { AppDataAdapter.appInfoList = appInfoList; notifyDataSetChanged(); } public AppDataAdapter(Context context, String key, int type) { mContext = context; mKey = key; mType = type; } /** * 在Adapter中设置一个过滤方法,目的是为了将过滤后的数据传入Adapter中并刷新数据 * * @param locationListModels */ @SuppressLint("NotifyDataSetChanged") public void setFilter(List locationListModels) { appInfoList = new ArrayList<>(); appInfoList.addAll(locationListModels); notifyDataSetChanged(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View rowItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_app_list, parent, false); return new ViewHolder(rowItem); } @Override public void onBindViewHolder(ViewHolder holder, int position) { AppData appInfo = appInfoList.get(position); selectedApps = PrefsUtils.mSharedPreferences.getStringSet(mKey, new LinkedHashSet<>()); holder.mAppListIcon.setImageBitmap(appInfo.icon); holder.mAppName.setText(appInfo.label); holder.mAppPackageName.setText(appInfo.packageName); holder.mSelecte.setChecked(shouldSelect(appInfo.packageName)); holder.mSelecte.setVisibility(mType != 0 ? View.GONE : View.VISIBLE); holder.itemView.setOnClickListener(v -> onItemClickListener.onItemClick(v, position, appInfo, holder.mSelecte.isChecked())); } public boolean shouldSelect(String pkgName) { return (selectedApps.contains(pkgName)); } public void setOnItemClickListener(onItemClickListener onItemClick) { this.onItemClickListener = onItemClick; } @Override public int getItemCount() { return appInfoList.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { private final ImageView mAppListIcon; private final TextView mAppName; private final TextView mAppPackageName; private final CheckBox mSelecte; public ViewHolder(View itemView) { super(itemView); mAppListIcon = itemView.findViewById(android.R.id.icon); mAppName = itemView.findViewById(android.R.id.title); mAppPackageName = itemView.findViewById(android.R.id.summary); mSelecte = itemView.findViewById(android.R.id.checkbox); } } public interface onItemClickListener { void onItemClick(View view, int position, AppData appData, boolean isCheck); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/data/adapter/ModSearchAdapter.java ================================================ package com.sevtinge.cemiuiler.data.adapter; import android.annotation.SuppressLint; import android.content.Context; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Filter; import android.widget.Filterable; import android.widget.ImageView; import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.data.ModData; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.SearchHelper; import java.util.ArrayList; import java.util.Comparator; import java.util.concurrent.CopyOnWriteArrayList; public class ModSearchAdapter extends RecyclerView.Adapter implements Filterable { private Context mContext; private String filterString = ""; private ItemFilter mFilter; private onItemClickListener mItemClickListener;//item点击监听 private final CopyOnWriteArrayList modsList = new CopyOnWriteArrayList(); public void setOnItemClickListener(onItemClickListener onItemClick) { mItemClickListener = onItemClick; } @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) { mContext = viewGroup.getContext(); View view= LayoutInflater.from(mContext).inflate(R.layout.item_search_result, viewGroup,false); //创建一个VIewHolder return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder viewHolder, int position) { ModData ad = modsList.get(position); int start = ad.title.toLowerCase().indexOf(filterString); if (start >= 0) { Spannable spannable = new SpannableString(ad.title); spannable.setSpan(new ForegroundColorSpan(SearchHelper.MARK_COLOR_VIBRANT), start, start + filterString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); viewHolder.mName.setText(spannable, TextView.BufferType.SPANNABLE); } else { viewHolder.mName.setText(ad.title); } viewHolder.mPackageName.setText(ad.breadcrumbs); //设置item点击监听事件 viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mItemClickListener.onItemClick(view, ad); } }); } @Override public int getItemCount() { return modsList.size(); } @Override public Filter getFilter() { // 如果ItemFilter对象为空,那么重写创建一个 if (mFilter == null) { mFilter = new ItemFilter(); } return mFilter; } public class ViewHolder extends RecyclerView.ViewHolder { private ImageView mIcon; private TextView mName; private TextView mPackageName; public ViewHolder(View itemView) { super(itemView); mIcon = itemView.findViewById(android.R.id.icon); mName = itemView.findViewById(android.R.id.title); mPackageName = itemView.findViewById(android.R.id.summary); } } public interface onItemClickListener { void onItemClick(View view, ModData ad); } private class ItemFilter extends Filter { @Override protected FilterResults performFiltering(CharSequence constraint) { filterString = constraint.toString().toLowerCase(); final ArrayList nlist = new ArrayList(); for (ModData filterableData: SearchHelper.allModsList) { if (constraint.toString().equals(SearchHelper.NEW_MODS_SEARCH_QUERY)) { if (SearchHelper.NEW_MODS.contains(filterableData.key)) { nlist.add(filterableData); } } else if (filterableData.title.toLowerCase().contains(filterString)) { nlist.add(filterableData); } } FilterResults results = new FilterResults(); results.values = nlist; results.count = nlist.size(); return results; } @SuppressLint("NotifyDataSetChanged") @Override protected void publishResults(CharSequence constraint, FilterResults results) { modsList.clear(); if (results.count > 0 && results.values != null) { modsList.addAll((ArrayList)results.values); } sortList(); notifyDataSetChanged(); } } private void sortList() { modsList.sort(new Comparator() { public int compare(ModData app1, ModData app2) { int breadcrumbs = app1.breadcrumbs.compareToIgnoreCase(app2.breadcrumbs); if (breadcrumbs == 0) return app1.title.compareToIgnoreCase(app2.title); else return breadcrumbs; } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/data/adapter/MutipleChoiceAdapter.java ================================================ package com.sevtinge.cemiuiler.data.adapter; import android.util.SparseBooleanArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.recyclerview.widget.RecyclerView; import com.sevtinge.cemiuiler.R; import java.util.List; import moralnorm.appcompat.widget.CheckedTextView; public class MutipleChoiceAdapter extends RecyclerView.Adapter { // 填充数据的list private List mList; // 用来控制CheckBox的选中状况 private SparseBooleanArray mIsChecked; private OnCurWillCheckAllChangedListener mListener; private boolean curWillCheckAll = true; public MutipleChoiceAdapter(List list) { mList = list; mIsChecked = new SparseBooleanArray(); // 初始化数据 initData(); } // 初始化isSelected的数据 private void initData() { for (int i = 0; i < mList.size(); i++) { getCheckedArray().put(i, false); } } public interface OnCurWillCheckAllChangedListener { void onCurWillCheckAllChanged(boolean curWillCheckAll); } public void setOnCurWillCheckAllChangedListener(OnCurWillCheckAllChangedListener listener) { this.mListener = listener; } public SparseBooleanArray getCheckedArray() { return mIsChecked; } public void setCheckedArray(SparseBooleanArray isChecked) { mIsChecked = isChecked; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_mutiplechoice, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { CheckedTextView mCheckBoxTitle = holder.mCheckBoxTitle; // 设置list中TextView的显示 mCheckBoxTitle.setText(mList.get(position)); // 根据isSelected来设置checkbox的选中状况 mCheckBoxTitle.setChecked(getCheckedArray().get(position)); holder.itemView.setOnClickListener(v -> { // 改变CheckBox的状态 mCheckBoxTitle.toggle(); // 将CheckBox的选中状况记录下来 getCheckedArray().put(position, mCheckBoxTitle.isChecked()); for (int i = 0; i < mIsChecked.size(); i++) { if (mIsChecked.valueAt(i)) { curWillCheckAll = false; break; } else { curWillCheckAll = true; } } if (mListener != null) { mListener.onCurWillCheckAllChanged(curWillCheckAll); } }); } @Override public int getItemCount() { return mList.size(); } public class ViewHolder extends RecyclerView.ViewHolder { public CheckedTextView mCheckBoxTitle; public ViewHolder(View itemView) { super(itemView); mCheckBoxTitle = itemView.findViewById(android.R.id.text1); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/AiAsst.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.aiasst.AiCaptions; public class AiAsst extends BaseModule { @Override public void handleLoadPackage() { initHook(new AiCaptions(), mPrefsMap.getBoolean("aiasst_ai_captions")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Aod.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.hook.aod.UnlockAlwaysOnDisplay; import com.sevtinge.cemiuiler.module.base.BaseModule; public class Aod extends BaseModule { @Override public void handleLoadPackage() { initHook(UnlockAlwaysOnDisplay.INSTANCE, mPrefsMap.getBoolean("aod_unlock_always_on_display")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Barrage.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.hook.barrage.*; import com.sevtinge.cemiuiler.module.base.BaseModule; public class Barrage extends BaseModule { @Override public void handleLoadPackage() { initHook(AnyBarrage.INSTANCE, mPrefsMap.getBoolean("barrage_any_barrage")); initHook(CustomBarrageLength.INSTANCE, mPrefsMap.getInt("barrage_custom_barrage_length", 36) != 36); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Browser.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.browser.DebugMode; import com.sevtinge.cemiuiler.module.hook.various.UnlockSuperClipboard; public class Browser extends BaseModule { @Override public void handleLoadPackage() { initHook(DebugMode.INSTANCE, mPrefsMap.getBoolean("browser_debug_mode")); // dexKit load initHook(LoadHostDir.INSTANCE); initHook(UnlockSuperClipboard.INSTANCE, mPrefsMap.getBoolean("various_super_clipboard_enable")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Camera.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.camera.EnableLabOptions; import com.sevtinge.cemiuiler.module.hook.camera.Unlock120Fps; import com.sevtinge.cemiuiler.module.hook.camera.Unlock60Fps; import com.sevtinge.cemiuiler.module.hook.camera.UnlockAiEnhance; import com.sevtinge.cemiuiler.module.hook.camera.UnlockAiShutter; import com.sevtinge.cemiuiler.module.hook.camera.UnlockAiWatermark; import com.sevtinge.cemiuiler.module.hook.camera.UnlockAmbilight; import com.sevtinge.cemiuiler.module.hook.camera.UnlockAudioZoom; import com.sevtinge.cemiuiler.module.hook.camera.UnlockClone; import com.sevtinge.cemiuiler.module.hook.camera.UnlockColorEnhance; import com.sevtinge.cemiuiler.module.hook.camera.UnlockCosmeticMirror; import com.sevtinge.cemiuiler.module.hook.camera.UnlockCvlens; import com.sevtinge.cemiuiler.module.hook.camera.UnlockCyberFocusVersion2; import com.sevtinge.cemiuiler.module.hook.camera.UnlockDoc; import com.sevtinge.cemiuiler.module.hook.camera.UnlockDualcam; import com.sevtinge.cemiuiler.module.hook.camera.UnlockDuration; import com.sevtinge.cemiuiler.module.hook.camera.UnlockFilm; import com.sevtinge.cemiuiler.module.hook.camera.UnlockFilmDelay; import com.sevtinge.cemiuiler.module.hook.camera.UnlockFilmDollyZoom; import com.sevtinge.cemiuiler.module.hook.camera.UnlockFilmDream; import com.sevtinge.cemiuiler.module.hook.camera.UnlockFilmSlowShutter; import com.sevtinge.cemiuiler.module.hook.camera.UnlockFilmTimeBackflow; import com.sevtinge.cemiuiler.module.hook.camera.UnlockFilmTimeFreeze; import com.sevtinge.cemiuiler.module.hook.camera.UnlockHandGesture; import com.sevtinge.cemiuiler.module.hook.camera.UnlockHdr; import com.sevtinge.cemiuiler.module.hook.camera.UnlockHeic; import com.sevtinge.cemiuiler.module.hook.camera.UnlockIdcard; import com.sevtinge.cemiuiler.module.hook.camera.UnlockLog; import com.sevtinge.cemiuiler.module.hook.camera.UnlockMakeup; import com.sevtinge.cemiuiler.module.hook.camera.UnlockMenMakeup; import com.sevtinge.cemiuiler.module.hook.camera.UnlockMilive; import com.sevtinge.cemiuiler.module.hook.camera.UnlockMoon; import com.sevtinge.cemiuiler.module.hook.camera.UnlockNevus; import com.sevtinge.cemiuiler.module.hook.camera.UnlockNewBeauty; import com.sevtinge.cemiuiler.module.hook.camera.UnlockPano; import com.sevtinge.cemiuiler.module.hook.camera.UnlockPixel; import com.sevtinge.cemiuiler.module.hook.camera.UnlockPortrait; import com.sevtinge.cemiuiler.module.hook.camera.UnlockRaw; import com.sevtinge.cemiuiler.module.hook.camera.UnlockSlow; import com.sevtinge.cemiuiler.module.hook.camera.UnlockTrackEyes; import com.sevtinge.cemiuiler.module.hook.camera.UnlockTrackFeature; import com.sevtinge.cemiuiler.module.hook.camera.UnlockTrackFocus; import com.sevtinge.cemiuiler.module.hook.camera.UnlockVideosky; import com.sevtinge.cemiuiler.module.hook.camera.UnlockVlog; import com.sevtinge.cemiuiler.module.hook.camera.UnlockVlogPro; public class Camera extends BaseModule { @Override public void handleLoadPackage() { // 功能 initHook(new UnlockAiWatermark(), mPrefsMap.getBoolean("camera_features_unlock_aiwatermark")); initHook(new UnlockAmbilight(), mPrefsMap.getBoolean("camera_features_unlock_ambilight")); initHook(new UnlockClone(), mPrefsMap.getBoolean("camera_features_unlock_clone")); initHook(new UnlockCosmeticMirror(), mPrefsMap.getBoolean("camera_features_unlock_cosmetic_mirror")); initHook(new UnlockDoc(), mPrefsMap.getBoolean("camera_features_unlock_doc")); initHook(new UnlockDualcam(), mPrefsMap.getBoolean("camera_features_unlock_dualcam")); initHook(new UnlockDuration(), mPrefsMap.getBoolean("camera_features_unlock_duration")); initHook(new UnlockIdcard(), mPrefsMap.getBoolean("camera_features_unlock_idcard")); initHook(new UnlockMilive(), mPrefsMap.getBoolean("camera_features_unlock_milive")); initHook(new UnlockMoon(), mPrefsMap.getBoolean("camera_features_unlock_moon")); initHook(new UnlockPano(), mPrefsMap.getBoolean("camera_features_unlock_pano")); initHook(new UnlockPixel(), mPrefsMap.getBoolean("camera_features_unlock_pixel")); initHook(new UnlockPortrait(), mPrefsMap.getBoolean("camera_features_unlock_portrait")); initHook(new UnlockSlow(), mPrefsMap.getBoolean("camera_features_unlock_slow")); initHook(new UnlockVideosky(), mPrefsMap.getBoolean("camera_features_unlock_videosky")); initHook(new UnlockVlog(), mPrefsMap.getBoolean("camera_features_unlock_vlog")); initHook(new UnlockVlogPro(), mPrefsMap.getBoolean("camera_features_unlock_vlog_pro")); initHook(new UnlockFilm(), mPrefsMap.getBoolean("camera_features_unlock_film")); initHook(new UnlockFilmDelay(), mPrefsMap.getBoolean("camera_features_unlock_film_delay")); initHook(new UnlockFilmDollyZoom(), mPrefsMap.getBoolean("camera_features_unlock_film_dollyzoom")); initHook(new UnlockFilmDream(), mPrefsMap.getBoolean("camera_features_unlock_film_dream")); initHook(new UnlockFilmSlowShutter(), mPrefsMap.getBoolean("camera_features_unlock_film_slowshutter")); initHook(new UnlockFilmTimeBackflow(), mPrefsMap.getBoolean("camera_features_unlock_film_timebackflow")); initHook(new UnlockFilmTimeFreeze(), mPrefsMap.getBoolean("camera_features_unlock_film_timefreeze")); // 拍照 initHook(new UnlockMakeup(), mPrefsMap.getBoolean("camera_shot_makeup")); initHook(new UnlockColorEnhance(), mPrefsMap.getBoolean("camera_shot_color_enhance")); initHook(new UnlockHandGesture(), mPrefsMap.getBoolean("camera_shot_hand_gesture")); // 录像 initHook(new Unlock60Fps(), mPrefsMap.getBoolean("camera_record_60fps")); initHook(new Unlock120Fps(), mPrefsMap.getBoolean("camera_record_120fps")); initHook(new UnlockHdr(), mPrefsMap.getBoolean("camera_record_hdr")); initHook(new UnlockAiEnhance(), mPrefsMap.getBoolean("camera_record_ai")); initHook(new UnlockAudioZoom(), mPrefsMap.getBoolean("camera_record_audio_zoom")); // 人像 initHook(new UnlockCvlens(), mPrefsMap.getBoolean("camera_portrait_cvlens")); initHook(new UnlockNewBeauty(), mPrefsMap.getBoolean("camera_portrait_new_beauty")); // 专业 initHook(new UnlockRaw(), mPrefsMap.getBoolean("camera_pro_raw")); initHook(new UnlockLog(), mPrefsMap.getBoolean("camera_pro_log")); // 设置 initHook(new UnlockTrackFeature(), (mPrefsMap.getBoolean("camera_settings_track_eyes") || mPrefsMap.getBoolean("camera_settings_track_focus"))); initHook(new UnlockHeic(), mPrefsMap.getBoolean("camera_settings_heic")); initHook(new UnlockTrackFocus(), mPrefsMap.getBoolean("camera_settings_track_focus")); initHook(new UnlockAiShutter(), mPrefsMap.getBoolean("camera_settings_predictive")); initHook(new UnlockCyberFocusVersion2(), mPrefsMap.getBoolean("camera_settings_track_focus")); initHook(new UnlockNevus(), mPrefsMap.getBoolean("camera_settings_nevus")); initHook(new UnlockMenMakeup(), mPrefsMap.getBoolean("camera_settings_men_makeup")); initHook(EnableLabOptions.INSTANCE, mPrefsMap.getBoolean("camera_settings_lab_options")); initHook(new UnlockTrackEyes(), mPrefsMap.getBoolean("camera_settings_track_eyes")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Clock.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.clock.EnableHourGlass; public class Clock extends BaseModule { @Override public void handleLoadPackage() { initHook(new EnableHourGlass(), mPrefsMap.getBoolean("clock_enable_hour_glass")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/ContentExtension.java ================================================ package com.sevtinge.cemiuiler.module.app; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.contentextension.DoublePress; import com.sevtinge.cemiuiler.module.hook.contentextension.HorizontalContentExtension; import com.sevtinge.cemiuiler.module.hook.contentextension.LinkOpenMode; import com.sevtinge.cemiuiler.module.hook.contentextension.SuperImage; import com.sevtinge.cemiuiler.module.hook.contentextension.UnlockTaplus; import com.sevtinge.cemiuiler.module.hook.contentextension.UseThirdPartyBrowser; public class ContentExtension extends BaseModule { @Override public void handleLoadPackage() { initHook(new UseThirdPartyBrowser(), mPrefsMap.getBoolean("content_extension_browser")); initHook(new DoublePress(), mPrefsMap.getBoolean("content_extension_double_press")); initHook(new SuperImage(), mPrefsMap.getBoolean("content_extension_super_image")); initHook(new LinkOpenMode()); initHook(HorizontalContentExtension.INSTANCE, mPrefsMap.getBoolean("content_extension_unlock_taplus_horizontal")); if (!isAndroidR()){ initHook(UnlockTaplus.INSTANCE, mPrefsMap.getBoolean("content_extension_unlock_taplus")); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Creation.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.creation.UnlockCreation; import com.sevtinge.cemiuiler.module.hook.various.UnlockSuperClipboard; public class Creation extends BaseModule { @Override public void handleLoadPackage() { initHook(UnlockCreation.INSTANCE, mPrefsMap.getBoolean("creation_unlock_enable")); initHook(UnlockSuperClipboard.INSTANCE, mPrefsMap.getBoolean("various_super_clipboard_enable")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Downloads.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.downloads.FuckXlDownload; public class Downloads extends BaseModule { @Override public void handleLoadPackage() { initHook(new FuckXlDownload(), mPrefsMap.getBoolean("various_fuck_xlDownload")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/ExternalStorage.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.externalstorage.DisableFolderCantUse; public class ExternalStorage extends BaseModule { @Override public void handleLoadPackage() { initHook(new DisableFolderCantUse(), mPrefsMap.getBoolean("various_disable_folder_cantuse")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/FileExplorer.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.fileexplorer.SelectName; import com.sevtinge.cemiuiler.module.hook.various.UnlockSuperClipboard; public class FileExplorer extends BaseModule { @Override public void handleLoadPackage() { initHook(SelectName.INSTANCE, mPrefsMap.getBoolean("file_explorer_can_selectable") || mPrefsMap.getBoolean("file_explorer_is_single_line")); initHook(UnlockSuperClipboard.INSTANCE, mPrefsMap.getBoolean("various_super_clipboard_enable")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Gallery.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.gallery.EnableHdrEnhance; import com.sevtinge.cemiuiler.module.hook.gallery.EnableIdPhoto; import com.sevtinge.cemiuiler.module.hook.gallery.EnableMagicSky; import com.sevtinge.cemiuiler.module.hook.gallery.EnableOcr; import com.sevtinge.cemiuiler.module.hook.gallery.EnableOcrForm; import com.sevtinge.cemiuiler.module.hook.gallery.EnablePdf; import com.sevtinge.cemiuiler.module.hook.gallery.EnablePhotoMovie; import com.sevtinge.cemiuiler.module.hook.gallery.EnableRemover2; import com.sevtinge.cemiuiler.module.hook.gallery.EnableTextYanhua; import com.sevtinge.cemiuiler.module.hook.gallery.EnableVideoPost; import com.sevtinge.cemiuiler.module.hook.various.UnlockSuperClipboard; public class Gallery extends BaseModule { @Override public void handleLoadPackage() { initHook(new EnableHdrEnhance(), mPrefsMap.getBoolean("gallery_enable_hdr_enhanced")); initHook(new EnableMagicSky(), mPrefsMap.getBoolean("gallery_enable_magic_sky")); initHook(new EnablePdf(), mPrefsMap.getBoolean("gallery_enable_pdf")); initHook(new EnablePhotoMovie(), mPrefsMap.getBoolean("gallery_enable_photo_movie")); initHook(new EnableRemover2(), mPrefsMap.getBoolean("gallery_enable_remover_2")); initHook(new EnableTextYanhua(), mPrefsMap.getBoolean("gallery_enable_text_yanhua")); initHook(new EnableIdPhoto(), mPrefsMap.getBoolean("gallery_enable_id_photo")); initHook(new EnableIdPhoto(), mPrefsMap.getBoolean("gallery_enable_magic_matting")); initHook(new EnableVideoPost(), mPrefsMap.getBoolean("gallery_enable_video_post")); initHook(new EnableVideoPost(), mPrefsMap.getBoolean("gallery_enable_video_editor")); initHook(new EnableOcr(), mPrefsMap.getBoolean("gallery_enable_ocr")); initHook(new EnableOcrForm(), mPrefsMap.getBoolean("gallery_enable_ocr_form")); initHook(UnlockSuperClipboard.INSTANCE, mPrefsMap.getBoolean("various_super_clipboard_enable")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/GlobalActions.java ================================================ package com.sevtinge.cemiuiler.module.app; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogE; import static java.lang.System.currentTimeMillis; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.view.KeyEvent; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.PrefsUtils; import de.robv.android.xposed.XposedHelpers; @SuppressLint("UnspecifiedRegisterReceiverFlag") public class GlobalActions extends BaseHook { @Override public void init() { setupGlobalActions(); setupRestartActions(); } // GlobalActions public void setupGlobalActions() { hookAllConstructors("com.android.server.accessibility.AccessibilityManagerService", new MethodHook() { @Override protected void after(MethodHookParam param) { Context mGlobalContext = (Context) param.args[0]; IntentFilter mFilter = new IntentFilter(); // Actions mFilter.addAction(ACTION_PREFIX + "ToggleColorInversion"); mFilter.addAction(ACTION_PREFIX + "LockScreen"); mFilter.addAction(ACTION_PREFIX + "GoToSleep"); mFilter.addAction(ACTION_PREFIX + "ScreenCapture"); mFilter.addAction(ACTION_PREFIX + "OpenPowerMenu"); mFilter.addAction(ACTION_PREFIX + "LaunchIntent"); mGlobalContext.registerReceiver(mGlobalReceiver, mFilter); } }); } public static void proxySystemProperties(String method, String prop, String val, ClassLoader classLoader) { XposedHelpers.callStaticMethod(XposedHelpers.findClassIfExists("android.os.SystemProperties", classLoader), method, prop, val); } @SuppressLint("UnsafeIntentLaunch") private final BroadcastReceiver mGlobalReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try { Class clsWMG = findClass("android.view.WindowManagerGlobal", null); Object wms = XposedHelpers.callStaticMethod(clsWMG, "getWindowManagerService"); String action = intent.getAction(); switch (action) { case ACTION_PREFIX + "ToggleColorInversion" -> { int opt = Settings.Secure.getInt(context.getContentResolver(), "accessibility_display_inversion_enabled"); int conflictProp = (int) Helpers.proxySystemProperties("getInt", "ro.df.effect.conflict", 0, null); int conflictProp2 = (int) Helpers.proxySystemProperties("getInt", "ro.vendor.df.effect.conflict", 0, null); boolean hasConflict = conflictProp == 1 || conflictProp2 == 1; Object dfMgr = XposedHelpers.callStaticMethod(XposedHelpers.findClass("miui.hardware.display.DisplayFeatureManager", null), "getInstance"); if (hasConflict && opt == 0) { XposedHelpers.callMethod(dfMgr, "setScreenEffect", 15, 1); } Settings.Secure.putInt(context.getContentResolver(), "accessibility_display_inversion_enabled", opt == 0 ? 1 : 0); if (hasConflict && opt != 0) { XposedHelpers.callMethod(dfMgr, "setScreenEffect", 15, 0); } } case ACTION_PREFIX + "LockScreen" -> { XposedHelpers.callMethod(context.getSystemService(Context.POWER_SERVICE), "goToSleep", SystemClock.uptimeMillis()); XposedHelpers.callMethod(wms, "lockNow", (Object) null); } case ACTION_PREFIX + "GoToSleep" -> XposedHelpers.callMethod(context.getSystemService(Context.POWER_SERVICE), "goToSleep", SystemClock.uptimeMillis()); case ACTION_PREFIX + "ScreenCapture" -> context.sendBroadcast(new Intent("android.intent.action.CAPTURE_SCREENSHOT")); case ACTION_PREFIX + "OpenPowerMenu" -> { clsWMG = findClass("android.view.WindowManagerGlobal"); wms = XposedHelpers.callStaticMethod(clsWMG, "getWindowManagerService"); XposedHelpers.callMethod(wms, "showGlobalActions"); } case ACTION_PREFIX + "LaunchIntent" -> { Intent launchIntent = intent.getParcelableExtra("intent"); if (launchIntent != null) { int user = 0; if (launchIntent.hasExtra("user")) { user = launchIntent.getIntExtra("user", 0); launchIntent.removeExtra("user"); } if (user != 0) { XposedHelpers.callMethod(context, "startActivityAsUser", launchIntent, XposedHelpers.newInstance(UserHandle.class, user)); } else { context.startActivity(launchIntent); } } } } } catch (Throwable t) { LogD(TAG, "onReceive", t); } } }; /** * RestartActions */ public void setupRestartActions() { hookAllMethods("com.android.server.policy.PhoneWindowManager", "init", new MethodHook() { @Override protected void after(MethodHookParam param) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); IntentFilter intentfilter = new IntentFilter(); intentfilter.addAction(ACTION_PREFIX + "RestartApps"); mContext.registerReceiver(mRestartReceiver, intentfilter); } }); } private static void forceStopPackage(Context context, String packageName) { ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); XposedHelpers.callMethod(am, "forceStopPackage", packageName); } private static final BroadcastReceiver mRestartReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try { String action = intent.getAction(); if (action == null) { return; } if ((ACTION_PREFIX + "RestartApps").equals(action)) { forceStopPackage(context, intent.getStringExtra("packageName")); } } catch (Exception e) { LogE("GlobalActions", null, e); } } }; public static boolean handleAction(Context context, String key) { return handleAction(context, key, false); } public static boolean handleAction(Context context, String key, boolean skipLock) { if (key == null || key.isEmpty()) { return false; } int action = PrefsUtils.getSharedIntPrefs(context, key + "_action", 0); if (action <= 0) { return false; } if (action >= 85 && action <= 88) { if (GlobalActions.isMediaActionsAllowed(context)) { GlobalActions.sendDownUpKeyEvent(context, action, false); } return true; } return switch (action) { case 1 -> setAction(context, "OpenNotificationCenter"); case 2 -> setAction(context, "ClearMemory"); case 3 -> setAction(context, "ToggleColorInversion"); case 4 -> setAction(context, "LockScreen"); case 5 -> setAction(context, "GoToSleep"); case 6 -> setAction(context, "ScreenCapture"); case 7 -> setAction(context, "OpenRecents"); case 8 -> setAction(context, "OpenVolumeDialog"); case 12 -> setAction(context, "OpenPowerMenu"); case 13 -> launchAppIntent(context, key, skipLock); /* case 3: return expandEQS(context); case 6: return takeScreenshot(context); case 7: return openRecents(context); case 8: return launchAppIntent(context, key, skipLock); case 9: return launchShortcutIntent(context, key, skipLock); case 20: return launchActivityIntent(context, key, skipLock); case 10: return toggleThis(context, Helpers.getSharedIntPref(context, key + "_toggle", 0)); case 11: return switchToPrevApp(context); case 12: return openPowerMenu(context); case 15: return goBack(context); case 16: return simulateMenu(context); case 18: return volumeUp(context); case 19: return volumeDown(context); case 21: return switchKeyboard(context); case 22: return switchOneHandedLeft(context); case 23: return switchOneHandedRight(context); case 24: return forceClose(context);*/ default -> false; }; } // Actions public static boolean setAction(Context context, String action) { try { context.sendBroadcast(new Intent(ACTION_PREFIX + action)); return true; } catch (Throwable t) { LogD("GlobalActions", "setAction", t); return false; } } /*public static boolean openNotificationCenter(Context context) { try { context.sendBroadcast(new Intent(ACTION_PREFIX + "ExpandNotifications")); return true; } catch (Throwable t) { LogUtils.log(t); return false; } } public static boolean goToSleep(Context context) { try { context.sendBroadcast(new Intent(ACTION_PREFIX + "GoToSleep")); return true; } catch (Throwable t) { LogUtils.log(t); return false; } }*/ public static boolean isMediaActionsAllowed(Context mContext) { AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); boolean isMusicActive = am.isMusicActive(); boolean isMusicActiveRemotely = (Boolean) XposedHelpers.callMethod(am, "isMusicActiveRemotely"); boolean isAllowed = isMusicActive || isMusicActiveRemotely; if (!isAllowed) { long mCurrentTime = currentTimeMillis(); long mLastPauseTime = Settings.System.getLong(mContext.getContentResolver(), "last_music_paused_time", mCurrentTime); if (mCurrentTime - mLastPauseTime < 10 * 60 * 1000) { isAllowed = true; } } return isAllowed; } public static void sendDownUpKeyEvent(Context mContext, int keyCode, boolean vibrate) { AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); am.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); am.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keyCode)); if (vibrate && PrefsUtils.getSharedBoolPrefs(mContext, "prefs_key_controls_volumemedia_vibrate", true)) ; /*Helpers.performStrongVibration(mContext, PrefsUtils.getSharedBoolPrefs(mContext, "prefa_key_controls_volumemedia_vibrate_ignore", false));*/ } public static boolean launchAppIntent(Context context, String key, boolean skipLock) { return launchIntent(context, getIntent(context, key, IntentType.APP, skipLock)); } public static boolean launchIntent(Context context, Intent intent) { if (intent == null) { return false; } Intent bIntent = new Intent(ACTION_PREFIX + "LaunchIntent"); bIntent.putExtra("intent", intent); context.sendBroadcast(bIntent); return true; } enum IntentType { APP, ACTIVITY, SHORTCUT } public static Intent getIntent(Context context, String prefs, IntentType intentType, boolean skipLock) { try { if (intentType == IntentType.APP) { prefs += "_app"; } else if (intentType == IntentType.ACTIVITY) { prefs += "_activity"; } else if (intentType == IntentType.SHORTCUT) { prefs += "_shortcut_intent"; } String prefValue = PrefsUtils.getSharedStringPrefs(context, prefs, null); if (prefValue == null) return null; Intent intent = new Intent(); if (intentType == IntentType.SHORTCUT) { intent = Intent.parseUri(prefValue, 0); } else { String[] pkgAppArray = prefValue.split("\\|"); if (pkgAppArray.length < 2) { return null; } ComponentName name = new ComponentName(pkgAppArray[0], pkgAppArray[1]); intent.setComponent(name); int user = PrefsUtils.getSharedIntPrefs(context, prefs + "_user", 0); if (user != 0) { intent.putExtra("user", user); } } intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); if (intentType == IntentType.APP) { intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); } if (skipLock) { intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); intent.putExtra("ShowCameraWhenLocked", true); intent.putExtra("StartActivityWhenLocked", true); } return intent; } catch (Throwable t) { LogD("GlobalActions", "getIntent", t); return null; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/GuardProvider.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.guardprovider.DisableUploadAppListNew; public class GuardProvider extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(DisableUploadAppListNew.INSTANCE, mPrefsMap.getBoolean("disable_upload_applist")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Home.java ================================================ package com.sevtinge.cemiuiler.module.app; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.home.AllAppsBlur; import com.sevtinge.cemiuiler.module.hook.home.AnimDurationRatio; import com.sevtinge.cemiuiler.module.hook.home.FreeFormCountForHome; import com.sevtinge.cemiuiler.module.hook.home.HideNavigationBar; import com.sevtinge.cemiuiler.module.hook.home.HomePortraitReverse; import com.sevtinge.cemiuiler.module.hook.home.MaxFreeForm; import com.sevtinge.cemiuiler.module.hook.home.ScreenSwipe; import com.sevtinge.cemiuiler.module.hook.home.SeekPoints; import com.sevtinge.cemiuiler.module.hook.home.SetDeviceLevel; import com.sevtinge.cemiuiler.module.hook.home.StickyFloatingWindowsForHome; import com.sevtinge.cemiuiler.module.hook.home.ToastSlideAgain; import com.sevtinge.cemiuiler.module.hook.home.UnlockHotseatIcon; import com.sevtinge.cemiuiler.module.hook.home.UserPresentAnimation; import com.sevtinge.cemiuiler.module.hook.home.WidgetCornerRadius; import com.sevtinge.cemiuiler.module.hook.home.WidgetCrack; import com.sevtinge.cemiuiler.module.hook.home.dock.DisableRecentsIcon; import com.sevtinge.cemiuiler.module.hook.home.dock.DockCustom; import com.sevtinge.cemiuiler.module.hook.home.dock.FoldDeviceDock; import com.sevtinge.cemiuiler.module.hook.home.dock.FoldDock; import com.sevtinge.cemiuiler.module.hook.home.dock.HideSeekPoint; import com.sevtinge.cemiuiler.module.hook.home.dock.ShowDockIconTitle; import com.sevtinge.cemiuiler.module.hook.home.drawer.AllAppsContainerViewBlur; import com.sevtinge.cemiuiler.module.hook.home.drawer.AppDrawer; import com.sevtinge.cemiuiler.module.hook.home.drawer.PinyinArrangement; import com.sevtinge.cemiuiler.module.hook.home.folder.BigFolderIcon; import com.sevtinge.cemiuiler.module.hook.home.folder.BigFolderIconBlur; import com.sevtinge.cemiuiler.module.hook.home.folder.BigFolderIconBlur1x2; import com.sevtinge.cemiuiler.module.hook.home.folder.BigFolderIconBlur2x1; import com.sevtinge.cemiuiler.module.hook.home.folder.BigFolderItemMaxCount; import com.sevtinge.cemiuiler.module.hook.home.folder.FolderAnimation; import com.sevtinge.cemiuiler.module.hook.home.folder.FolderAutoClose; import com.sevtinge.cemiuiler.module.hook.home.folder.FolderBlur; import com.sevtinge.cemiuiler.module.hook.home.folder.FolderColumns; import com.sevtinge.cemiuiler.module.hook.home.folder.FolderShade; import com.sevtinge.cemiuiler.module.hook.home.folder.FolderVerticalPadding; import com.sevtinge.cemiuiler.module.hook.home.folder.SmallFolderIconBlur; import com.sevtinge.cemiuiler.module.hook.home.gesture.DoubleTap; import com.sevtinge.cemiuiler.module.hook.home.gesture.HotSeatSwipe; import com.sevtinge.cemiuiler.module.hook.home.gesture.QuickBack; import com.sevtinge.cemiuiler.module.hook.home.gesture.ShakeDevice; import com.sevtinge.cemiuiler.module.hook.home.layout.HotSeatsHeight; import com.sevtinge.cemiuiler.module.hook.home.layout.HotSeatsMarginBottom; import com.sevtinge.cemiuiler.module.hook.home.layout.HotSeatsMarginTop; import com.sevtinge.cemiuiler.module.hook.home.layout.SearchBarMarginBottom; import com.sevtinge.cemiuiler.module.hook.home.layout.UnlockGrids; import com.sevtinge.cemiuiler.module.hook.home.layout.WorkspacePadding; import com.sevtinge.cemiuiler.module.hook.home.mipad.EnableHideGestureLine; import com.sevtinge.cemiuiler.module.hook.home.mipad.EnableMoreSetting; import com.sevtinge.cemiuiler.module.hook.home.navigation.BackGestureAreaHeight; import com.sevtinge.cemiuiler.module.hook.home.navigation.BackGestureAreaWidth; import com.sevtinge.cemiuiler.module.hook.home.other.AlwaysBlurWallpaper; import com.sevtinge.cemiuiler.module.hook.home.other.AlwaysShowStatusClock; import com.sevtinge.cemiuiler.module.hook.home.other.BlurRadius; import com.sevtinge.cemiuiler.module.hook.home.other.BlurWhenShowShortcutMenu; import com.sevtinge.cemiuiler.module.hook.home.other.DisableHideGoogle; import com.sevtinge.cemiuiler.module.hook.home.other.FixAndroidRS; import com.sevtinge.cemiuiler.module.hook.home.other.FreeformShortcutMenu; import com.sevtinge.cemiuiler.module.hook.home.other.HomeMode; import com.sevtinge.cemiuiler.module.hook.home.other.InfiniteScroll; import com.sevtinge.cemiuiler.module.hook.home.other.OverlapMode; import com.sevtinge.cemiuiler.module.hook.home.other.ShortcutItemCount; import com.sevtinge.cemiuiler.module.hook.home.other.ShowAllHideApp; import com.sevtinge.cemiuiler.module.hook.home.recent.AlwaysShowCleanUp; import com.sevtinge.cemiuiler.module.hook.home.recent.BlurLevel; import com.sevtinge.cemiuiler.module.hook.home.recent.CardTextColor; import com.sevtinge.cemiuiler.module.hook.home.recent.CardTextSize; import com.sevtinge.cemiuiler.module.hook.home.recent.DisableRecentViewWallpaperDarken; import com.sevtinge.cemiuiler.module.hook.home.recent.FreeformCardBackgroundColor; import com.sevtinge.cemiuiler.module.hook.home.recent.HideCleanUp; import com.sevtinge.cemiuiler.module.hook.home.recent.HideFreeform; import com.sevtinge.cemiuiler.module.hook.home.recent.HideStatusBarWhenEnterRecent; import com.sevtinge.cemiuiler.module.hook.home.recent.MemInfoShow; import com.sevtinge.cemiuiler.module.hook.home.recent.RealMemory; import com.sevtinge.cemiuiler.module.hook.home.recent.RecentResource; import com.sevtinge.cemiuiler.module.hook.home.recent.RecentText; import com.sevtinge.cemiuiler.module.hook.home.recent.RemoveCardAnim; import com.sevtinge.cemiuiler.module.hook.home.recent.RemoveIcon; import com.sevtinge.cemiuiler.module.hook.home.recent.TaskViewHorizontal; import com.sevtinge.cemiuiler.module.hook.home.recent.TaskViewVertical; import com.sevtinge.cemiuiler.module.hook.home.title.AnimParamCustom; import com.sevtinge.cemiuiler.module.hook.home.title.BigIconCorner; import com.sevtinge.cemiuiler.module.hook.home.title.DisableHideFile; import com.sevtinge.cemiuiler.module.hook.home.title.DisableHideTheme; import com.sevtinge.cemiuiler.module.hook.home.title.DownloadAnimation; import com.sevtinge.cemiuiler.module.hook.home.title.EnableIconMonoChrome; import com.sevtinge.cemiuiler.module.hook.home.title.FixAnimation; import com.sevtinge.cemiuiler.module.hook.home.title.HiddenAllTitle; import com.sevtinge.cemiuiler.module.hook.home.title.IconTitleColor; import com.sevtinge.cemiuiler.module.hook.home.title.LargeIconCornerRadius; import com.sevtinge.cemiuiler.module.hook.home.title.NewInstallIndicator; import com.sevtinge.cemiuiler.module.hook.home.title.PerfectIcon; import com.sevtinge.cemiuiler.module.hook.home.title.TitleFontSize; import com.sevtinge.cemiuiler.module.hook.home.title.TitleMarquee; import com.sevtinge.cemiuiler.module.hook.home.widget.AllWidgetAnimation; import com.sevtinge.cemiuiler.module.hook.home.widget.AllowMoveAllWidgetToMinus; import com.sevtinge.cemiuiler.module.hook.home.widget.AlwaysShowMiuiWidget; import com.sevtinge.cemiuiler.module.hook.home.widget.HideWidgetTitles; import com.sevtinge.cemiuiler.module.hook.home.widget.ResizableWidgets; import com.sevtinge.cemiuiler.module.hook.systemframework.mipad.SetGestureNeedFingerNum; import java.util.Objects; public class Home extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); // 手势 initHook(new QuickBack(), mPrefsMap.getBoolean("home_navigation_quick_back")); initHook(new DoubleTap(), mPrefsMap.getInt("home_gesture_double_tap_action", 0) > 0); initHook(new ScreenSwipe(), mPrefsMap.getInt("home_gesture_up_swipe_action", 0) > 0 || mPrefsMap.getInt("home_gesture_down_swipe_action", 0) > 0 || mPrefsMap.getInt("home_gesture_up_swipe2_action", 0) > 0 || mPrefsMap.getInt("home_gesture_down_swipe2_action", 0) > 0); initHook(new HotSeatSwipe(), mPrefsMap.getInt("home_gesture_left_swipe_action", 0) > 0 || mPrefsMap.getInt("home_gesture_right_swipe_action", 0) > 0); initHook(new ShakeDevice(), mPrefsMap.getInt("home_gesture_shake_action", 0) > 0); // initHook(new SwipeAndStop(), mPrefsMap.getInt("home_gesture_swipe_and_stop_action" ,0) > 0); initHook(new BackGestureAreaHeight(), mPrefsMap.getInt("home_navigation_back_area_height", 60) != 60); initHook(new BackGestureAreaWidth(), mPrefsMap.getInt("home_navigation_back_area_width", 100) != 100); // 布局 initHook(new UnlockGrids(), mPrefsMap.getBoolean("home_layout_unlock_grids")); // initHook(new UnlockGridsNoWord(), mPrefsMap.getBoolean("home_layout_unlock_grids_no_word")); initHook(new WorkspacePadding(), mPrefsMap.getBoolean("home_layout_workspace_padding_bottom_enable") || mPrefsMap.getBoolean("home_layout_workspace_padding_top_enable")); initHook(new HotSeatsHeight(), mPrefsMap.getBoolean("home_layout_hotseats_height_enable")); initHook(new HotSeatsMarginTop(), mPrefsMap.getBoolean("home_layout_hotseats_margin_top_enable")); initHook(new HotSeatsMarginBottom(), mPrefsMap.getBoolean("home_layout_hotseats_margin_bottom_enable")); initHook(new SearchBarMarginBottom(), (mPrefsMap.getInt("home_layout_searchbar_margin_bottom", 0) > 0) && mPrefsMap.getBoolean("home_layout_searchbar_margin_bottom_enable")); // 文件夹 initHook(FolderAutoClose.INSTANCE, mPrefsMap.getBoolean("home_folder_auto_close")); initHook(new FolderShade(), mPrefsMap.getStringAsInt("home_folder_shade", 1) > 0); initHook(FolderColumns.INSTANCE, mPrefsMap.getInt("home_folder_columns", 3) != 3 || mPrefsMap.getBoolean("home_folder_width")); initHook(new FolderAnimation(), mPrefsMap.getBoolean("home_folder_animation")); initHook(new SmallFolderIconBlur(), mPrefsMap.getBoolean("home_small_folder_icon_bg")); initHook(FolderVerticalPadding.INSTANCE, mPrefsMap.getInt("home_folder_vertical_padding", 0) != 0); initHook(new BigFolderIcon(), false); initHook(new BigFolderIconBlur2x1(), mPrefsMap.getBoolean("home_big_folder_icon_bg_2x1")); initHook(new BigFolderIconBlur1x2(), mPrefsMap.getBoolean("home_big_folder_icon_bg_1x2")); initHook(new BigFolderIconBlur(), mPrefsMap.getBoolean("home_big_folder_icon_bg")); initHook(new BigFolderItemMaxCount(), mPrefsMap.getBoolean("home_big_folder_item_max_count")); // 抽屉 initHook(AppDrawer.INSTANCE, mPrefsMap.getBoolean("home_drawer_all") || mPrefsMap.getBoolean("home_drawer_editor")); initHook(AllAppsContainerViewBlur.INSTANCE, mPrefsMap.getBoolean("home_drawer_blur") && !isAndroidR()); initHook(new PinyinArrangement(), mPrefsMap.getBoolean("home_drawer_pinyin")); // 最近任务 initHook(BlurLevel.INSTANCE, mPrefsMap.getStringAsInt("home_recent_blur_level", 6) != 6); initHook(DisableRecentViewWallpaperDarken.INSTANCE, mPrefsMap.getBoolean("home_recent_disable_wallpaper_dimming")); initHook(HideStatusBarWhenEnterRecent.INSTANCE, true); initHook(RemoveCardAnim.INSTANCE, mPrefsMap.getBoolean("home_recent_modify_animation")); initHook(TaskViewHorizontal.INSTANCE); initHook(TaskViewVertical.INSTANCE); initHook(HideFreeform.INSTANCE, mPrefsMap.getBoolean("home_recent_hide_freeform")); initHook(HideCleanUp.INSTANCE, mPrefsMap.getBoolean("home_recent_hide_clean_up")); initHook(FreeformCardBackgroundColor.INSTANCE); initHook(CardTextColor.INSTANCE); initHook(CardTextSize.INSTANCE); initHook(RecentText.INSTANCE, !Objects.equals(mPrefsMap.getString("home_recent_text", ""), "")); initHook(RemoveIcon.INSTANCE, mPrefsMap.getBoolean("home_recent_remove_icon")); initHook(RecentResource.INSTANCE, mPrefsMap.getInt("task_view_corners", 20) != 20 || mPrefsMap.getInt("task_view_header_height", 40) != 40); initHook(RealMemory.INSTANCE, mPrefsMap.getBoolean("home_recent_show_real_memory")); initHook(MemInfoShow.INSTANCE, mPrefsMap.getBoolean("home_recent_show_memory_info") && isPad()); initHook(AlwaysShowCleanUp.INSTANCE, mPrefsMap.getBoolean("always_show_clean_up")); // 图标 initHook(BigIconCorner.INSTANCE, mPrefsMap.getBoolean("home_title_big_icon_corner")); initHook(new DownloadAnimation(), mPrefsMap.getBoolean("home_title_download_animation")); initHook(DisableHideTheme.INSTANCE, mPrefsMap.getBoolean("home_title_disable_hide_theme")); initHook(DisableHideFile.INSTANCE, mPrefsMap.getBoolean("home_title_disable_hide_file")); initHook(new AnimParamCustom(), mPrefsMap.getBoolean("home_title_custom_anim_param_main")); // initHook(new IconScaleHook()/*, mPrefsMap.getInt("home_title_icon_scale", 100) != 100*/); // 标题 initHook(new TitleMarquee(), mPrefsMap.getBoolean("home_title_title_marquee")); initHook(new NewInstallIndicator(), mPrefsMap.getBoolean("home_title_title_new_install")); initHook(new HiddenAllTitle(), mPrefsMap.getBoolean("home_drawer_font_hidden")); initHook(new TitleFontSize(), mPrefsMap.getInt("home_title_font_size", 12) != 12); initHook(IconTitleColor.INSTANCE); initHook(new UnlockHotseatIcon(), mPrefsMap.getBoolean("home_dock_unlock_hotseat")); // 小部件 initHook(new AllWidgetAnimation(), mPrefsMap.getBoolean("home_widget_all_widget_animation")); initHook(AlwaysShowMiuiWidget.INSTANCE, mPrefsMap.getBoolean("home_widget_show_miui_widget")); initHook(AllowMoveAllWidgetToMinus.INSTANCE, mPrefsMap.getBoolean("home_widget_allow_moved_to_minus_one_screen")); initHook(new WidgetCornerRadius(), mPrefsMap.getInt("home_widget_corner_radius", 0) > 0); initHook(HideWidgetTitles.INSTANCE, mPrefsMap.getBoolean("home_widget_hide_title")); initHook(ResizableWidgets.INSTANCE, mPrefsMap.getBoolean("home_widget_resizable")); // 底栏 initHook(new DockCustom(), mPrefsMap.getBoolean("home_dock_bg_custom_enable")); initHook(new SeekPoints(), mPrefsMap.getStringAsInt("home_other_seek_points", 0) > 0); initHook(FoldDeviceDock.INSTANCE, mPrefsMap.getBoolean("home_dock_fold")); initHook(HideSeekPoint.INSTANCE, mPrefsMap.getBoolean("home_dock_hide_seekpoint")); initHook(ShowDockIconTitle.INSTANCE, mPrefsMap.getBoolean("home_dock_icon_title")); initHook(new HideNavigationBar(), mPrefsMap.getBoolean("system_ui_hide_navigation_bar")); initHook(DisableRecentsIcon.INSTANCE, mPrefsMap.getBoolean("home_dock_disable_recents_icon")); // 其他 initHook(new HomeMode(), mPrefsMap.getStringAsInt("home_other_home_mode", 0) > 0); initHook(AlwaysShowStatusClock.INSTANCE, mPrefsMap.getBoolean("home_other_show_clock")); initHook(new InfiniteScroll(), mPrefsMap.getBoolean("home_other_infinite_scroll")); initHook(new FreeformShortcutMenu(), (mPrefsMap.getBoolean("home_other_freeform_shortcut_menu") || (mPrefsMap.getBoolean("home_other_tasks_shortcut_menu")))); initHook(new UserPresentAnimation(), mPrefsMap.getBoolean("home_other_user_present_animation")); initHook(new PerfectIcon(), mPrefsMap.getBoolean("home_other_perfect_icon")); initHook(new EnableIconMonoChrome(), mPrefsMap.getBoolean("home_other_icon_mono_chrome")); initHook(new HomePortraitReverse(), mPrefsMap.getBoolean("home_other_portrait_reverse")); initHook(AlwaysBlurWallpaper.INSTANCE, mPrefsMap.getBoolean("home_other_always_blur_launcher_wallpaper")); initHook(BlurRadius.INSTANCE, mPrefsMap.getInt("home_other_blur_radius", 100) != 100); initHook(ShortcutItemCount.INSTANCE, mPrefsMap.getBoolean("home_other_shortcut_remove_restrictions")); initHook(DisableHideGoogle.INSTANCE, mPrefsMap.getBoolean("home_other_disable_hide_google")); initHook(ShowAllHideApp.INSTANCE); // 桌面快捷方式管理 initHook(FixAndroidRS.INSTANCE, mPrefsMap.getBoolean("home_other_fix_android_r_s")); // 实验性功能 initHook(BlurWhenShowShortcutMenu.INSTANCE, mPrefsMap.getBoolean("home_other_shortcut_background_blur") && !isAndroidR()); initHook(FolderBlur.INSTANCE, mPrefsMap.getBoolean("home_folder_blur") && !isAndroidR()); initHook(new FoldDock(), mPrefsMap.getBoolean("home_other_fold_dock")); initHook(new AllAppsBlur(), !isAndroidR()); initHook(new FixAnimation(), mPrefsMap.getBoolean("home_title_fix_animation")); initHook(new LargeIconCornerRadius(), mPrefsMap.getBoolean("home_large_icon_enable")); // 多小窗 initHook(new FreeFormCountForHome(), mPrefsMap.getBoolean("system_framework_freeform_count")); initHook(new MaxFreeForm(), mPrefsMap.getBoolean("system_framework_freeform_count")); // Fold2样式负一屏 initHook(new OverlapMode(), mPrefsMap.getBoolean("personal_assistant_overlap_mode") && !isAndroidR()); // Other initHook(new ToastSlideAgain(), mPrefsMap.getBoolean("home_other_toast_slide_again")); initHook(new StickyFloatingWindowsForHome(), mPrefsMap.getBoolean("system_framework_freeform_sticky")); initHook(new WidgetCrack(), mPrefsMap.getBoolean("various_enable_super_function") && mPrefsMap.getBoolean("personal_assistant_widget_crack")); initHook(AnimDurationRatio.INSTANCE, true); initHook(SetDeviceLevel.INSTANCE, mPrefsMap.getBoolean("home_other_high_models")); // 小米/红米平板相关 boolean mMoreSetting = mPrefsMap.getBoolean("home_other_mi_pad_enable_more_setting") && isPad(); initHook(SetGestureNeedFingerNum.INSTANCE, mPrefsMap.getBoolean("mipad_input_need_finger_num") && isPad()); initHook(EnableMoreSetting.INSTANCE, mMoreSetting); initHook(EnableHideGestureLine.INSTANCE, mMoreSetting); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/InCallUi.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.incallui.AnswerInHeadUp; import com.sevtinge.cemiuiler.module.hook.incallui.HideCrbt; public class InCallUi extends BaseModule { @Override public void handleLoadPackage() { initHook(new HideCrbt(), mPrefsMap.getBoolean("incallui_hide_crbt")); initHook(new AnswerInHeadUp(), mPrefsMap.getBoolean("incallui_answer_in_head_up")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Joyose.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.joyose.DisableCloudControl; import com.sevtinge.cemiuiler.module.hook.joyose.EnableGpuTuner; public class Joyose extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(DisableCloudControl.INSTANCE, mPrefsMap.getBoolean("various_disable_cloud_control")); initHook(EnableGpuTuner.INSTANCE, mPrefsMap.getBoolean("joyose_enable_gpu_tuner")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Lbe.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.lbe.DisableClipboardTip; public class Lbe extends BaseModule { @Override public void handleLoadPackage() { initHook(DisableClipboardTip.INSTANCE, mPrefsMap.getBoolean("lbe_clipboard_tip_toast")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Market.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.market.DeviceModify; public class Market extends BaseModule { @Override public void handleLoadPackage() { initHook(new DeviceModify(), mPrefsMap.getStringAsInt("market_device_modify_new", 0) != 0);; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/MediaEditor.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.mediaeditor.FilterManagerAll; import com.sevtinge.cemiuiler.module.hook.mediaeditor.UnlockMinimumCropLimitNew; public class MediaEditor extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(UnlockMinimumCropLimitNew.INSTANCE, mPrefsMap.getBoolean("mediaeditor_unlock_minimum_crop_limit")); initHook(FilterManagerAll.INSTANCE, mPrefsMap.getBoolean("mediaeditor_filter_manager")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/MiLink.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.milink.UnlockMiShare; public class MiLink extends BaseModule { @Override public void handleLoadPackage() { initHook(new UnlockMiShare(), mPrefsMap.getBoolean("milink_unlock_mishare")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/MiSettings.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.misettings.CustomRefreshRate; import com.sevtinge.cemiuiler.module.hook.misettings.ShowMoreFpsList; public class MiSettings extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(CustomRefreshRate.INSTANCE, mPrefsMap.getBoolean("various_custom_refresh_rate")); initHook(ShowMoreFpsList.INSTANCE, mPrefsMap.getBoolean("mi_settings_show_fps")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/MiShare.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.mishare.NoAutoTurnOff; import com.sevtinge.cemiuiler.module.hook.mishare.UnlockTurboMode; public class MiShare extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(NoAutoTurnOff.INSTANCE, mPrefsMap.getBoolean("disable_mishare_auto_off")); initHook(UnlockTurboMode.INSTANCE, mPrefsMap.getBoolean("unlock_turbo_mode")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/MiWallpaper.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.miwallpaper.UnlockSuperWallpaper; public class MiWallpaper extends BaseModule { @Override public void handleLoadPackage() { initHook(new UnlockSuperWallpaper(), mPrefsMap.getBoolean("miwallpaper_unlock_super_wallpaper")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Mirror.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.mirror.UnlockMiuiPlus; public class Mirror extends BaseModule { @Override public void handleLoadPackage() { initHook(new UnlockMiuiPlus(), mPrefsMap.getBoolean("mirror_unlock_miui_plus")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Mms.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.mms.DisableAd; import com.sevtinge.cemiuiler.module.hook.various.UnlockSuperClipboard; public class Mms extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(DisableAd.INSTANCE, mPrefsMap.getBoolean("mms_disable_ad")); initHook(UnlockSuperClipboard.INSTANCE, mPrefsMap.getBoolean("various_super_clipboard_enable")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Mtb.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.mtb.BypassAuthentication; import com.sevtinge.cemiuiler.module.hook.mtb.IsUserBuild; public class Mtb extends BaseModule { @Override public void handleLoadPackage() { initHook(BypassAuthentication.INSTANCE, mPrefsMap.getBoolean("mtb_auth")); initHook(IsUserBuild.INSTANCE, mPrefsMap.getBoolean("mtb_auth")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Music.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.music.DisableAd; public class Music extends BaseModule { @Override public void handleLoadPackage() { initHook(new DisableAd(), mPrefsMap.getBoolean("music_disable_ad")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/NetworkBoost.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.networkboost.LinkTurboToast; public class NetworkBoost extends BaseModule { @Override public void handleLoadPackage() { initHook(new LinkTurboToast(), mPrefsMap.getBoolean("various_disable_link_turbo_toast")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Nfc.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.nfc.*; public class Nfc extends BaseModule { @Override public void handleLoadPackage() { initHook(new DisableSound(), mPrefsMap.getBoolean("nfc_disable_sound")); initHook(new AllowInformationScreen(), mPrefsMap.getBoolean("nfc_allow_information_screen")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Notes.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.various.UnlockSuperClipboard; public class Notes extends BaseModule { @Override public void handleLoadPackage() { initHook(UnlockSuperClipboard.INSTANCE, mPrefsMap.getBoolean("various_super_clipboard_enable")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/PackageInstaller.java ================================================ package com.sevtinge.cemiuiler.module.app; import android.text.TextUtils; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.packageinstaller.AllAsSystemApp; import com.sevtinge.cemiuiler.module.hook.packageinstaller.DisableAD; import com.sevtinge.cemiuiler.module.hook.packageinstaller.DisableCountChecking; import com.sevtinge.cemiuiler.module.hook.packageinstaller.DisableSafeModelTip; import com.sevtinge.cemiuiler.module.hook.packageinstaller.DisplayMoreApkInfoNew; import com.sevtinge.cemiuiler.module.hook.packageinstaller.InstallRiskDisable; import com.sevtinge.cemiuiler.module.hook.packageinstaller.InstallSource; import com.sevtinge.cemiuiler.module.hook.packageinstaller.SafeMode; public class PackageInstaller extends BaseModule { public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); // /*initHook(new MiuiPackageInstallModify(), mPrefsMap.getBoolean("miui_package_installer_modify"));*/ // 纯净模式 initHook(new SafeMode()); // 禁用广告 initHook(DisableAD.INSTANCE, mPrefsMap.getBoolean("miui_package_installer_disable_ad")); // 禁用风险检测 initHook(InstallRiskDisable.INSTANCE, mPrefsMap.getBoolean("miui_package_installer_install_risk")); // 禁用安全守护提示 initHook(DisableSafeModelTip.INSTANCE, mPrefsMap.getBoolean("miui_package_installer_safe_model_tip")); // 允许更新系统应用 initHook(AllAsSystemApp.INSTANCE, mPrefsMap.getBoolean("miui_package_installer_update_system_app")); // 自定义安装来源 initHook(new InstallSource(), !TextUtils.isEmpty(mPrefsMap.getString("miui_package_installer_install_source", "com.android.fileexplorer"))); // 显示更多安装包信息 // initHook(new DisplayMoreApkInfo(), mPrefsMap.getBoolean("miui_package_installer_apk_info")); initHook(DisplayMoreApkInfoNew.INSTANCE, mPrefsMap.getBoolean("miui_package_installer_apk_info")); // 禁用频繁安装应用检查 initHook(DisableCountChecking.INSTANCE, mPrefsMap.getBoolean("miui_package_installer_count_checking")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/PersonalAssistant.java ================================================ package com.sevtinge.cemiuiler.module.app; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.personalassistant.BlurOverlay; import com.sevtinge.cemiuiler.module.hook.personalassistant.BlurPersonalAssistant; import com.sevtinge.cemiuiler.module.hook.personalassistant.BlurPersonalAssistantBackGround; import com.sevtinge.cemiuiler.module.hook.personalassistant.EnableFoldWidget; import com.sevtinge.cemiuiler.module.hook.personalassistant.WidgetCrack; public class PersonalAssistant extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(new BlurOverlay(), false); initHook(new EnableFoldWidget(), mPrefsMap.getBoolean("personal_assistant_fold_widget_enable")); if (mPrefsMap.getStringAsInt("personal_assistant_value", 1) != 1 && !isAndroidR()) { initHook(BlurPersonalAssistant.INSTANCE, mPrefsMap.getBoolean("pa_enable")); } else { initHook(BlurPersonalAssistantBackGround.INSTANCE, mPrefsMap.getBoolean("pa_enable")); } initHook(new WidgetCrack(), mPrefsMap.getBoolean("various_enable_super_function") && mPrefsMap.getBoolean("personal_assistant_widget_crack")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Phone.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.phone.DualNrSupport; import com.sevtinge.cemiuiler.module.hook.phone.DualSaSupport; import com.sevtinge.cemiuiler.module.hook.phone.ModemFeature; import com.sevtinge.cemiuiler.module.hook.phone.N1BandPhone; import com.sevtinge.cemiuiler.module.hook.phone.N28BandPhone; import com.sevtinge.cemiuiler.module.hook.phone.N5N8BandPhone; import com.sevtinge.cemiuiler.module.hook.phone.ViceSlotVolteButton; public class Phone extends BaseModule { @Override public void handleLoadPackage() { initHook(ModemFeature.INSTANCE, mPrefsMap.getBoolean("phone_smart_dual_sim")); initHook(ViceSlotVolteButton.INSTANCE, mPrefsMap.getBoolean("phone_vice_slot_volte")); initHook(DualNrSupport.INSTANCE, mPrefsMap.getBoolean("phone_double_5g_nr")); initHook(DualSaSupport.INSTANCE, mPrefsMap.getBoolean("phone_double_5g_sa")); initHook(N1BandPhone.INSTANCE, mPrefsMap.getBoolean("phone_n1")); initHook(N5N8BandPhone.INSTANCE, mPrefsMap.getBoolean("phone_n5_n8")); initHook(N28BandPhone.INSTANCE, mPrefsMap.getBoolean("phone_n28")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/PowerKeeper.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.powerkeeper.CustomRefreshRate; import com.sevtinge.cemiuiler.module.hook.powerkeeper.DontKillApps; import com.sevtinge.cemiuiler.module.hook.powerkeeper.LockMaxFps; import com.sevtinge.cemiuiler.module.hook.powerkeeper.PreventBatteryWitelist; public class PowerKeeper extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(CustomRefreshRate.INSTANCE, mPrefsMap.getBoolean("various_custom_refresh_rate")); initHook(LockMaxFps.INSTANCE, mPrefsMap.getBoolean("powerkeeper_lock_max_fps")); initHook(DontKillApps.INSTANCE, mPrefsMap.getBoolean("powerkeeper_do_not_kill_apps")); initHook(new PreventBatteryWitelist(), mPrefsMap.getBoolean("powerkeeper_prevent_recovery_of_battery_optimization_whitelist")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Scanner.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.scanner.EnableCard; import com.sevtinge.cemiuiler.module.hook.scanner.EnableDocPpt; import com.sevtinge.cemiuiler.module.hook.scanner.EnableOcr; import com.sevtinge.cemiuiler.module.hook.scanner.EnableTranslation; import com.sevtinge.cemiuiler.module.hook.scanner.document.EnableDocument; import com.sevtinge.cemiuiler.module.hook.scanner.document.EnableExcel; import com.sevtinge.cemiuiler.module.hook.scanner.document.EnablePpt; public class Scanner extends BaseModule { @Override public void handleLoadPackage() { initHook(new EnableOcr(), mPrefsMap.getBoolean("scanner_ocr")); initHook(new EnableExcel(), mPrefsMap.getBoolean("scanner_excel")); initHook(new EnablePpt(), mPrefsMap.getBoolean("scanner_ppt")); initHook(new EnableCard(), mPrefsMap.getBoolean("scanner_card")); initHook(new EnableTranslation(), mPrefsMap.getBoolean("scanner_translation")); initHook(new EnableDocument(), mPrefsMap.getBoolean("scanner_document")); initHook(new EnableDocPpt(), mPrefsMap.getBoolean("scanner_doc_ppt")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/ScreenRecorder.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.screenrecorder.ForceSupportPlaybackCapture; import com.sevtinge.cemiuiler.module.hook.screenrecorder.SaveToMovies; import com.sevtinge.cemiuiler.module.hook.screenrecorder.ScreenRecorderConfig; import com.sevtinge.cemiuiler.module.hook.screenrecorder.UnlockMoreVolumeFrom; public class ScreenRecorder extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(new ForceSupportPlaybackCapture(), mPrefsMap.getBoolean("screenrecorder_force_support_playback_capture")); initHook(new UnlockMoreVolumeFrom(), mPrefsMap.getBoolean("screenrecorder_more_volume")); initHook(ScreenRecorderConfig.INSTANCE, mPrefsMap.getBoolean("screenrecorder_config")); initHook(SaveToMovies.INSTANCE, mPrefsMap.getBoolean("screenrecorder_save_to_movies")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/ScreenShot.java ================================================ package com.sevtinge.cemiuiler.module.app; import android.text.TextUtils; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.screenshot.DeviceShellCustomize; import com.sevtinge.cemiuiler.module.hook.screenshot.SaveToPictures; import com.sevtinge.cemiuiler.module.hook.screenshot.UnlockMinimumCropLimit; import com.sevtinge.cemiuiler.module.hook.screenshot.UnlockPrivacyMarking; import com.sevtinge.cemiuiler.module.hook.various.UnlockSuperClipboard; public class ScreenShot extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(UnlockMinimumCropLimit.INSTANCE, mPrefsMap.getBoolean("screenshot_unlock_minimum_crop_limit")); initHook(SaveToPictures.INSTANCE, mPrefsMap.getBoolean("screenshot_save_to_pictures")); initHook(DeviceShellCustomize.INSTANCE, !TextUtils.isEmpty(mPrefsMap.getString("screenshot_device_customize", ""))); initHook(UnlockPrivacyMarking.INSTANCE, mPrefsMap.getBoolean("screenshot_unlock_privacy_marking")); // 超级剪切板 initHook(UnlockSuperClipboard.INSTANCE, mPrefsMap.getBoolean("various_super_clipboard_enable")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/SecurityCenter.java ================================================ package com.sevtinge.cemiuiler.module.app; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.securitycenter.AppLockPinScramble; import com.sevtinge.cemiuiler.module.hook.securitycenter.BlurSecurity; import com.sevtinge.cemiuiler.module.hook.securitycenter.DisableReport; import com.sevtinge.cemiuiler.module.hook.securitycenter.GetBubbleAppString; import com.sevtinge.cemiuiler.module.hook.securitycenter.IsSbnBelongToActiveBubbleApp; import com.sevtinge.cemiuiler.module.hook.securitycenter.NewBoxBlur; import com.sevtinge.cemiuiler.module.hook.securitycenter.RemoveConversationBubbleSettingsRestriction; import com.sevtinge.cemiuiler.module.hook.securitycenter.RemoveOpenAppConfirmationPopup; import com.sevtinge.cemiuiler.module.hook.securitycenter.SidebarLineCustom; import com.sevtinge.cemiuiler.module.hook.securitycenter.VideoDolbyOpen; import com.sevtinge.cemiuiler.module.hook.securitycenter.app.AppDefaultSort; import com.sevtinge.cemiuiler.module.hook.securitycenter.app.AppDetails; import com.sevtinge.cemiuiler.module.hook.securitycenter.app.AppDisable; import com.sevtinge.cemiuiler.module.hook.securitycenter.app.AppRestrict; import com.sevtinge.cemiuiler.module.hook.securitycenter.app.OpenByDefaultSetting; import com.sevtinge.cemiuiler.module.hook.securitycenter.battery.ScreenUsedTime; import com.sevtinge.cemiuiler.module.hook.securitycenter.battery.ShowBatteryTemperatureNew; import com.sevtinge.cemiuiler.module.hook.securitycenter.battery.UnlockSmartCharge; import com.sevtinge.cemiuiler.module.hook.securitycenter.battery.UnlockSuperWirelessCharge; import com.sevtinge.cemiuiler.module.hook.securitycenter.beauty.BeautyFace; import com.sevtinge.cemiuiler.module.hook.securitycenter.beauty.BeautyLightAuto; import com.sevtinge.cemiuiler.module.hook.securitycenter.beauty.BeautyPc; import com.sevtinge.cemiuiler.module.hook.securitycenter.beauty.BeautyPrivacy; import com.sevtinge.cemiuiler.module.hook.securitycenter.lab.AiClipboardEnable; import com.sevtinge.cemiuiler.module.hook.securitycenter.lab.BlurLocationEnable; import com.sevtinge.cemiuiler.module.hook.securitycenter.lab.GetNumberEnable; import com.sevtinge.cemiuiler.module.hook.securitycenter.other.DisableRootCheck; import com.sevtinge.cemiuiler.module.hook.securitycenter.other.FuckRiskPkg; import com.sevtinge.cemiuiler.module.hook.securitycenter.other.LockOneHundredPoints; import com.sevtinge.cemiuiler.module.hook.securitycenter.other.NoLowBatteryWarning; import com.sevtinge.cemiuiler.module.hook.securitycenter.other.SkipCountDownLimit; import com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.AddSideBarExpandReceiver; import com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.game.RemoveMacroBlackList; import com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.game.UnlockGunService; import com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.video.DisableRemoveScreenHoldOn; import com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.video.UnlockEnhanceContours; import com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.video.UnlockMemc; import com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.video.UnlockSuperResolution; public class SecurityCenter extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); // 应用管理 initHook(new AppDefaultSort(), mPrefsMap.getStringAsInt("security_center_app_default_sort", 0) > 0); initHook(new AppRestrict(), mPrefsMap.getBoolean("security_center_app_restrict")); initHook(new AppDisable(), mPrefsMap.getBoolean("security_center_app_disable")); initHook(new AppDetails(), mPrefsMap.getBoolean("security_center_app_details")); initHook(DisableReport.INSTANCE, mPrefsMap.getBoolean("security_center_disable_ban")); initHook(OpenByDefaultSetting.INSTANCE, mPrefsMap.getBoolean("security_center_app_default_setting")); // 省电与电池 // initHook(new ShowBatteryTemperature(), mPrefsMap.getBoolean("security_center_show_battery_temperature")); initHook(ShowBatteryTemperatureNew.INSTANCE, mPrefsMap.getBoolean("security_center_show_battery_temperature")); initHook(UnlockSuperWirelessCharge.INSTANCE, mPrefsMap.getBoolean("security_center_super_wireless_charge")); initHook(ScreenUsedTime.INSTANCE, mPrefsMap.getBoolean("security_center_unlock_screen_time")); initHook(UnlockSmartCharge.INSTANCE, mPrefsMap.getBoolean("security_center_unlock_smart_charge")); // 隐私保护 initHook(new AppLockPinScramble(), mPrefsMap.getBoolean("security_center_applock_pin_scramble")); initHook(AiClipboardEnable.INSTANCE, mPrefsMap.getBoolean("security_center_ai_clipboard")); initHook(BlurLocationEnable.INSTANCE, mPrefsMap.getBoolean("security_center_blur_location")); initHook(GetNumberEnable.INSTANCE, mPrefsMap.getBoolean("security_center_get_number")); // 前置摄像助手 initHook(BeautyLightAuto.INSTANCE, mPrefsMap.getBoolean("security_center_beauty_light_auto")); initHook(BeautyFace.INSTANCE, mPrefsMap.getBoolean("security_center_beauty_face")); initHook(BeautyPrivacy.INSTANCE, mPrefsMap.getBoolean("security_center_beauty_privacy")); initHook(BeautyPc.INSTANCE, mPrefsMap.getBoolean("security_center_beauty_pc")); // 其他 initHook(LockOneHundredPoints.INSTANCE, mPrefsMap.getBoolean("security_center_score")); initHook(new SkipCountDownLimit(), mPrefsMap.getBoolean("security_center_skip_count_down_limit")); initHook(DisableRootCheck.INSTANCE, mPrefsMap.getBoolean("security_center_disable_root_check")); initHook(FuckRiskPkg.INSTANCE, mPrefsMap.getBoolean("security_center_disable_send_malicious_app_notification")); initHook(NoLowBatteryWarning.INSTANCE, mPrefsMap.getBoolean("security_center_remove_low_battery_reminder")); // 小窗和气泡通知 initHook(new RemoveConversationBubbleSettingsRestriction(), mPrefsMap.getBoolean("security_center_remove_conversation_bubble_settings_restriction")); initHook(IsSbnBelongToActiveBubbleApp.INSTANCE, mPrefsMap.getBoolean("security_center_unlock_side_hide_freeform")); initHook(GetBubbleAppString.INSTANCE, mPrefsMap.getBoolean("security_center_unlock_side_hide_freeform")); // 移除打开应用弹窗 initHook(new RemoveOpenAppConfirmationPopup(), mPrefsMap.getBoolean("security_center_remove_open_app_confirmation_popup")); // 全局侧边栏 if (!isAndroidR()) { initHook(new NewBoxBlur(), mPrefsMap.getBoolean("security_center_newbox_custom_enable")); initHook(BlurSecurity.INSTANCE, mPrefsMap.getBoolean("se_enable")); initHook(SidebarLineCustom.INSTANCE, mPrefsMap.getBoolean("security_center_sidebar_line_color")); } initHook(new RemoveMacroBlackList(), mPrefsMap.getBoolean("security_center_remove_macro_black_list")); initHook(UnlockGunService.INSTANCE, mPrefsMap.getBoolean("security_center_unlock_gun_service")); initHook(DisableRemoveScreenHoldOn.INSTANCE, mPrefsMap.getBoolean("security_center_disable_remove_screen_hold_on")); initHook(UnlockMemc.INSTANCE, mPrefsMap.getBoolean("security_center_unlock_memc")); initHook(UnlockSuperResolution.INSTANCE, mPrefsMap.getBoolean("security_center_unlock_s_resolution")); initHook(UnlockEnhanceContours.INSTANCE, mPrefsMap.getBoolean("security_center_unlock_enhance_contours")); initHook(new AddSideBarExpandReceiver(), mPrefsMap.getBoolean("security_center_hide_sidebar")); // initHook(new DisableDockSuggest(), mPrefsMap.getBoolean("security_center_disable_sidebar_show_suggest")); initHook(new VideoDolbyOpen(), mPrefsMap.getBoolean("security_center_dolby_open")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Settings.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.settings.CemiuilerSettings; import com.sevtinge.cemiuiler.module.hook.settings.NotificationImportance; import com.sevtinge.cemiuiler.module.hook.settings.VolumeSeparateControlForSettings; public class Settings extends BaseModule { @Override public void handleLoadPackage() { initHook(new NotificationImportance(), mPrefsMap.getBoolean("settings_notfication_importance")); // initHook(new BluetoothRestrict(), mPrefsMap.getBoolean("various_disable_bluetooth_restrict")); initHook(new VolumeSeparateControlForSettings(), mPrefsMap.getBoolean("system_framework_volume_separate_control")); initHook(new CemiuilerSettings(), mPrefsMap.getStringAsInt("settings_icon", 0) != 0); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/SystemFramework.java ================================================ package com.sevtinge.cemiuiler.module.app; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.systemframework.AllowUntrustedTouch; import com.sevtinge.cemiuiler.module.hook.systemframework.AppDisableService; import com.sevtinge.cemiuiler.module.hook.systemframework.AppLinkVerify; import com.sevtinge.cemiuiler.module.hook.systemframework.CleanOpenMenu; import com.sevtinge.cemiuiler.module.hook.systemframework.CleanShareMenu; import com.sevtinge.cemiuiler.module.hook.systemframework.DeleteOnPostNotification; import com.sevtinge.cemiuiler.module.hook.systemframework.DisableCleaner; import com.sevtinge.cemiuiler.module.hook.systemframework.DisableFreeformBlackList; import com.sevtinge.cemiuiler.module.hook.systemframework.DisablePinVerifyPer72h; import com.sevtinge.cemiuiler.module.hook.systemframework.FlagSecure; import com.sevtinge.cemiuiler.module.hook.systemframework.FreeFormCount; import com.sevtinge.cemiuiler.module.hook.systemframework.FreeformBubble; import com.sevtinge.cemiuiler.module.hook.systemframework.MultiFreeFormSupported; import com.sevtinge.cemiuiler.module.hook.systemframework.PackagePermissions; import com.sevtinge.cemiuiler.module.hook.systemframework.RemoveSmallWindowRestrictions; import com.sevtinge.cemiuiler.module.hook.systemframework.ScreenRotation; import com.sevtinge.cemiuiler.module.hook.systemframework.SpeedInstall; import com.sevtinge.cemiuiler.module.hook.systemframework.StickyFloatingWindows; import com.sevtinge.cemiuiler.module.hook.systemframework.ThemeProvider; import com.sevtinge.cemiuiler.module.hook.systemframework.ThermalBrightness; import com.sevtinge.cemiuiler.module.hook.systemframework.UseOriginalAnimation; import com.sevtinge.cemiuiler.module.hook.systemframework.VolumeDefaultStream; import com.sevtinge.cemiuiler.module.hook.systemframework.VolumeDisableSafe; import com.sevtinge.cemiuiler.module.hook.systemframework.VolumeFirstPress; import com.sevtinge.cemiuiler.module.hook.systemframework.VolumeMediaSteps; import com.sevtinge.cemiuiler.module.hook.systemframework.VolumeSeparateControl; import com.sevtinge.cemiuiler.module.hook.systemframework.VolumeSteps; import com.sevtinge.cemiuiler.module.hook.systemframework.corepatch.BypassSignCheckForT; import com.sevtinge.cemiuiler.module.hook.systemframework.display.DisplayCutout; import com.sevtinge.cemiuiler.module.hook.systemframework.display.ToastTime; import com.sevtinge.cemiuiler.module.hook.systemframework.freeform.OpenAppInFreeForm; import com.sevtinge.cemiuiler.module.hook.systemframework.mipad.IgnoreStylusKeyGesture; import com.sevtinge.cemiuiler.module.hook.systemframework.mipad.NoMagicPointer; import com.sevtinge.cemiuiler.module.hook.systemframework.mipad.RemoveStylusBluetoothRestriction; import com.sevtinge.cemiuiler.module.hook.systemframework.mipad.RestoreEsc; import com.sevtinge.cemiuiler.module.hook.systemframework.mipad.SetGestureNeedFingerNum; import com.sevtinge.cemiuiler.module.hook.systemframework.network.DualNRSupport; import com.sevtinge.cemiuiler.module.hook.systemframework.network.DualSASupport; import com.sevtinge.cemiuiler.module.hook.systemframework.network.N1Band; import com.sevtinge.cemiuiler.module.hook.systemframework.network.N28Band; import com.sevtinge.cemiuiler.module.hook.systemframework.network.N5N8Band; import com.sevtinge.cemiuiler.module.hook.various.NoAccessDeviceLogsRequest; import de.robv.android.xposed.XposedBridge; public class SystemFramework extends BaseModule { @Override public void handleLoadPackage() { if (mPrefsMap.getBoolean("settings_disable_detailed_log")) XposedBridge.log("[Cemiuiler][I]: Detail log is disabled."); // 小窗 initHook(new FreeFormCount(), mPrefsMap.getBoolean("system_framework_freeform_count")); initHook(new FreeformBubble(), mPrefsMap.getBoolean("system_framework_freeform_bubble")); initHook(new DisableFreeformBlackList(), mPrefsMap.getBoolean("system_framework_disable_freeform_blacklist")); initHook(RemoveSmallWindowRestrictions.INSTANCE, mPrefsMap.getBoolean("system_framework_disable_freeform_blacklist")); initHook(new StickyFloatingWindows(), mPrefsMap.getBoolean("system_framework_freeform_sticky")); initHook(MultiFreeFormSupported.INSTANCE, mPrefsMap.getBoolean("system_framework_freeform_recents_to_small_freeform")); initHook(new OpenAppInFreeForm(), mPrefsMap.getBoolean("system_framework_freeform_jump")); // initHook(new OpenAppInFreeForm(), mPrefsMap.getBoolean("system_framework_freeform_jump")); // 音量 initHook(new VolumeDefaultStream()); initHook(new VolumeFirstPress(), mPrefsMap.getBoolean("system_framework_volume_first_press")); initHook(new VolumeSeparateControl(), mPrefsMap.getBoolean("system_framework_volume_separate_control")); initHook(new VolumeSteps(), mPrefsMap.getInt("system_framework_volume_steps", 0) > 0); initHook(new VolumeMediaSteps(), mPrefsMap.getBoolean("system_framework_volume_media_steps_enable")); initHook(new VolumeDisableSafe(), mPrefsMap.getBoolean("system_framework_volume_disable_safe")); // initHook(new ClockShowSecond(), mPrefsMap.getBoolean("system_ui_statusbar_clock_show_second")); initHook(new ThemeProvider(), mPrefsMap.getBoolean("various_enable_super_function") && mPrefsMap.getBoolean("various_theme_crack")); // 其他 initHook(new ScreenRotation(), mPrefsMap.getBoolean("system_framework_screen_all_rotations")); initHook(new CleanShareMenu(), mPrefsMap.getBoolean("system_framework_clean_share_menu")); initHook(new CleanOpenMenu(), mPrefsMap.getBoolean("system_framework_clean_open_menu")); initHook(new AllowUntrustedTouch(), mPrefsMap.getBoolean("system_framework_allow_untrusted_touch")); initHook(new FlagSecure(), mPrefsMap.getBoolean("system_other_flag_secure")); initHook(new AppLinkVerify(), mPrefsMap.getBoolean("system_framework_disable_app_link_verify")); initHook(new UseOriginalAnimation(), mPrefsMap.getBoolean("system_framework_other_use_original_animation")); initHook(new SpeedInstall(), mPrefsMap.getBoolean("system_framework_other_speed_install")); initHook(DeleteOnPostNotification.INSTANCE, mPrefsMap.getBoolean("system_other_delete_on_post_notification")); initHook(NoAccessDeviceLogsRequest.INSTANCE, mPrefsMap.getBoolean("various_disable_access_device_logs")); // 显示 initHook(DisplayCutout.INSTANCE, mPrefsMap.getBoolean("system_ui_display_hide_cutout_enable")); initHook(new ToastTime(), mPrefsMap.getBoolean("system_ui_display_toast_times_enable")); // initHook(new AutoBrightness(), mPrefsMap.getBoolean("system_control_center_auto_brightness")); // 位置模拟 // initHook(new LocationSimulation(), false); // 小米/红米平板设置相关 if (isPad()) { initHook(IgnoreStylusKeyGesture.INSTANCE, mPrefsMap.getBoolean("mipad_input_ingore_gesture")); initHook(NoMagicPointer.INSTANCE, mPrefsMap.getBoolean("mipad_input_close_magic")); initHook(RemoveStylusBluetoothRestriction.INSTANCE, mPrefsMap.getBoolean("mipad_input_disable_bluetooth")); initHook(RestoreEsc.INSTANCE, mPrefsMap.getBoolean("mipad_input_restore_esc")); initHook(SetGestureNeedFingerNum.INSTANCE, mPrefsMap.getBoolean("mipad_input_need_finger_num")); } // 核心破解 if (isMoreAndroidVersion(33)) { initHook(BypassSignCheckForT.INSTANCE, mPrefsMap.getBoolean("system_framework_core_patch_auth_creak") || mPrefsMap.getBoolean("system_framework_core_patch_disable_integrity")); } // 网络 initHook(DualNRSupport.INSTANCE, mPrefsMap.getBoolean("phone_double_5g_nr")); initHook(DualSASupport.INSTANCE, mPrefsMap.getBoolean("phone_double_5g_sa")); initHook(N1Band.INSTANCE, mPrefsMap.getBoolean("phone_n1")); initHook(N5N8Band.INSTANCE, mPrefsMap.getBoolean("phone_n5_n8")); initHook(N28Band.INSTANCE, mPrefsMap.getBoolean("phone_n28")); // Other initHook(new PackagePermissions()); initHook(new GlobalActions(), mLoadPackageParam.processName.equals("android")); initHook(new AppDisableService()); initHook(new ThermalBrightness(), mPrefsMap.getBoolean("system_framework_other_thermal_brightness")); initHook(DisableCleaner.INSTANCE, mPrefsMap.getBoolean("system_framework_other_disable_cleaner")); initHook(new DisablePinVerifyPer72h(), mPrefsMap.getBoolean("system_framework_disable_72h_verify")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/SystemFrameworkForCorePatch.java ================================================ package com.sevtinge.cemiuiler.module.app; import android.os.Build; import com.sevtinge.cemiuiler.module.hook.systemframework.corepatch.CorePatchForR; import com.sevtinge.cemiuiler.module.hook.systemframework.corepatch.CorePatchForS; import com.sevtinge.cemiuiler.module.hook.systemframework.corepatch.CorePatchForT; import com.sevtinge.cemiuiler.module.hook.systemframework.corepatch.CorePatchForU; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.IXposedHookZygoteInit; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class SystemFrameworkForCorePatch implements IXposedHookLoadPackage, IXposedHookZygoteInit { public static final String TAG = "CorePatch"; @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { if (("android".equals(lpparam.packageName)) && (lpparam.processName.equals("android"))) { XposedLogUtils.logI(TAG, "Current sdk version " + Build.VERSION.SDK_INT); switch (Build.VERSION.SDK_INT) { case Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> // 34 new CorePatchForU().handleLoadPackage(lpparam); case Build.VERSION_CODES.TIRAMISU -> // 33 new CorePatchForT().handleLoadPackage(lpparam); case Build.VERSION_CODES.S_V2 -> // 32 new CorePatchForS().handleLoadPackage(lpparam); case Build.VERSION_CODES.S -> // 31 new CorePatchForS().handleLoadPackage(lpparam); case Build.VERSION_CODES.R -> // 30 new CorePatchForR().handleLoadPackage(lpparam); default -> XposedLogUtils.logW(TAG, "Unsupported Version of Android " + Build.VERSION.SDK_INT); } } } @Override public void initZygote(StartupParam startupParam) throws Throwable { if (startupParam.startsSystemServer) { XposedLogUtils.logI(TAG, "Current sdk version " + Build.VERSION.SDK_INT); switch (Build.VERSION.SDK_INT) { case Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> // 34 new CorePatchForU().initZygote(startupParam); case Build.VERSION_CODES.TIRAMISU -> // 33 new CorePatchForT().initZygote(startupParam); case Build.VERSION_CODES.S_V2 -> // 32 new CorePatchForS().initZygote(startupParam); case Build.VERSION_CODES.S -> // 31 new CorePatchForS().initZygote(startupParam); case Build.VERSION_CODES.R -> // 30 new CorePatchForR().initZygote(startupParam); default -> XposedLogUtils.logW(TAG, "Unsupported Version of Android " + Build.VERSION.SDK_INT); } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/SystemSettings.java ================================================ package com.sevtinge.cemiuiler.module.app; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.systemsettings.AddMiuiPlusEntry; import com.sevtinge.cemiuiler.module.hook.systemsettings.AppsFreezerEnable; import com.sevtinge.cemiuiler.module.hook.systemsettings.EnableFoldArea; import com.sevtinge.cemiuiler.module.hook.systemsettings.EnablePadArea; import com.sevtinge.cemiuiler.module.hook.systemsettings.EnableSpeedMode; import com.sevtinge.cemiuiler.module.hook.systemsettings.InternationalBuild; import com.sevtinge.cemiuiler.module.hook.systemsettings.NewNFCPage; import com.sevtinge.cemiuiler.module.hook.systemsettings.NoveltyHaptic; import com.sevtinge.cemiuiler.module.hook.systemsettings.QuickManageOverlayPermission; import com.sevtinge.cemiuiler.module.hook.systemsettings.QuickManageUnknownAppSources; import com.sevtinge.cemiuiler.module.hook.systemsettings.UnLockAreaScreenshot; import com.sevtinge.cemiuiler.module.hook.systemsettings.UnlockTaplusForSettings; import com.sevtinge.cemiuiler.module.hook.systemsettings.ViewWifiPasswordHook; import com.sevtinge.cemiuiler.module.hook.systemsettings.VoipAssistantController; import com.sevtinge.cemiuiler.module.hook.systemsettings.aiimage.UnlockAi; import com.sevtinge.cemiuiler.module.hook.systemsettings.aiimage.UnlockMemc; import com.sevtinge.cemiuiler.module.hook.systemsettings.aiimage.UnlockSuperResolution; public class SystemSettings extends BaseModule { @Override public void handleLoadPackage() { initHook(new ViewWifiPasswordHook(), mPrefsMap.getBoolean("system_settings_safe_wifi")); initHook(new VoipAssistantController(), mPrefsMap.getBoolean("system_settings_voip_assistant_controller")); initHook(new AddMiuiPlusEntry(), mPrefsMap.getBoolean("mirror_unlock_miui_plus")); initHook(new EnableSpeedMode(), mPrefsMap.getBoolean("system_settings_develop_speed_mode")); initHook(new QuickManageOverlayPermission(), mPrefsMap.getBoolean("system_settings_permission_show_app_up")); initHook(new QuickManageUnknownAppSources(), mPrefsMap.getBoolean("system_settings_permission_unknown_origin_app")); initHook(new InternationalBuild(), mPrefsMap.getBoolean("system_settings_international_build")); initHook(new NewNFCPage(), mPrefsMap.getBoolean("system_settings_new_nfc_page")); initHook(new AppsFreezerEnable(), mPrefsMap.getBoolean("system_settings_apps_freezer")); initHook(new UnlockSuperResolution(), mPrefsMap.getBoolean("system_settings_ai_image_unlock_sr")); initHook(new UnlockAi(), mPrefsMap.getBoolean("system_settings_ai_image_unlock_ai")); initHook(new UnlockMemc(), mPrefsMap.getBoolean("system_settings_ai_image_unlock_memc")); initHook(UnLockAreaScreenshot.INSTANCE, mPrefsMap.getBoolean("system_settings_area_screenshot")); initHook(NoveltyHaptic.INSTANCE, mPrefsMap.getBoolean("system_settings_novelty_haptic")); initHook(new EnablePadArea(),mPrefsMap.getBoolean("system_settings_enable_pad_area")); initHook(new EnableFoldArea(),mPrefsMap.getBoolean("system_settings_enable_fold_area")); if (!isAndroidR()) { initHook(UnlockTaplusForSettings.INSTANCE, mPrefsMap.getBoolean("content_extension_unlock_taplus")); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/SystemUI.java ================================================ package com.sevtinge.cemiuiler.module.app; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.systemui.AutoCollapse; import com.sevtinge.cemiuiler.module.hook.systemui.BluetoothRestrict; import com.sevtinge.cemiuiler.module.hook.systemui.ChargeAnimationStyle; import com.sevtinge.cemiuiler.module.hook.systemui.HideNavigationBar; import com.sevtinge.cemiuiler.module.hook.systemui.MonetThemeOverlay; import com.sevtinge.cemiuiler.module.hook.systemui.NotificationFix; import com.sevtinge.cemiuiler.module.hook.systemui.NotificationFreeform; import com.sevtinge.cemiuiler.module.hook.systemui.OriginChargeAnimation; import com.sevtinge.cemiuiler.module.hook.systemui.QSDetailBackGround; import com.sevtinge.cemiuiler.module.hook.systemui.StatusBarActions; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.AddBlurEffectToNotificationView; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.CCGrid; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.CompactNotificationsHook; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.ControlCenterStyle; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.FiveGTile; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.FixMediaControlPanel; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.FlashLight; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.GmsTile; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.MuteVisibleNotifications; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.NotificationWeather; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.NotificationWeatherNew; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.NotificationWeatherOld; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.QQSGrid; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.QQSGridOld; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.QSControlDetailBackgroundAlpha; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.QSGrid; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.QSGridLabels; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.QSGridOld; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.RedirectToNotificationChannelSetting; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.SunlightMode; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.SwitchCCAndNotification; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.AddBlurEffectToLockScreen; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.BlurButton; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.ChargingCVP; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.ClockDisplaySeconds; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.ForceClockUseSystemFontsHook; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.HideLockScreenHint; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.HideLockScreenStatusBar; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.HideLockscreenZenMode; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.LockScreenDoubleTapToSleep; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.NoPassword; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.RemoveCamera; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.RemoveSmartScreen; import com.sevtinge.cemiuiler.module.hook.systemui.lockscreen.ScramblePIN; import com.sevtinge.cemiuiler.module.hook.systemui.navigation.HandleLineCustom; import com.sevtinge.cemiuiler.module.hook.systemui.navigation.NavigationCustom; import com.sevtinge.cemiuiler.module.hook.systemui.plugin.PluginHelper; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.DisplayHardwareDetail; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.DoubleTapToSleep; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.DualRowSignalHook; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.HideStatusBarBeforeScreenshot; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.MobileNetwork; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.NotificationIconColumns; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.SelectiveHideIconForAlarmClock; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.WifiStandard; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.clock.TimeCustomization; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.clock.TimeStyle; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.BatteryStyle; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.BluetoothIcon; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.DataSaverIcon; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.HideBatteryIcon; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.HideVoWiFiIcon; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.IconsFromSystemManager; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.StatusBarIcon; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.StatusBarIconPositionAdjust; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.StatusBarSimIcon; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all.WifiNetworkIndicator; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.t.UseNewHD; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.layout.StatusBarLayout; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.model.MobileTypeSingleHook; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.model.MobileTypeTextCustom; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network.NetworkSpeed; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network.NetworkSpeedSec; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network.NetworkSpeedSpacing; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network.NetworkSpeedStyle; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network.StatusBarNoNetSpeedSep; import com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network.s.NetworkSpeedWidth; import java.util.Objects; public class SystemUI extends BaseModule { @Override public void handleLoadPackage() { // 充电动画 initHook(new ChargeAnimationStyle(), mPrefsMap.getStringAsInt("system_ui_charge_animation_style", 0) > 0); initHook(new OriginChargeAnimation(), mPrefsMap.getBoolean("system_ui_origin_charge_animation")); // 小窗 initHook(new NotificationFreeform(), mPrefsMap.getBoolean("system_ui_notification_freeform")); // 禁用蓝牙临时关闭 initHook(new BluetoothRestrict(), mPrefsMap.getBoolean("various_disable_bluetooth_restrict")); // Monet initHook(new MonetThemeOverlay(), mPrefsMap.getBoolean("system_ui_monet_overlay_custom")); // 状态栏图标 initHook(WifiNetworkIndicator.INSTANCE, mPrefsMap.getStringAsInt("system_ui_status_bar_icon_wifi_network_indicator", 0) > 0); initHook(new StatusBarIcon()); initHook(new IconsFromSystemManager()); initHook(new WifiStandard(), mPrefsMap.getStringAsInt("system_ui_status_bar_icon_wifi_standard", 0) > 0); initHook(new BluetoothIcon(), mPrefsMap.getStringAsInt("system_ui_status_bar_icon_bluetooth", 0) != 0); initHook(new SelectiveHideIconForAlarmClock(), mPrefsMap.getStringAsInt("system_ui_status_bar_icon_alarm_clock", 0) == 3 && mPrefsMap.getInt("system_ui_status_bar_icon_alarm_clock_n", 0) > 0); initHook(NotificationIconColumns.INSTANCE, mPrefsMap.getBoolean("system_ui_status_bar_notification_dots_maximum_enable") || mPrefsMap.getBoolean("system_ui_status_bar_notification_icon_maximum_enable")); initHook(UseNewHD.INSTANCE, mPrefsMap.getBoolean("system_ui_status_bar_use_new_hd")); initHook(new HideStatusBarBeforeScreenshot(), mPrefsMap.getBoolean("system_ui_status_bar_hide_icon")); initHook(StatusBarSimIcon.INSTANCE); initHook(HideVoWiFiIcon.INSTANCE, mPrefsMap.getBoolean("system_ui_status_bar_icon_vowifi")); initHook(new DataSaverIcon(), mPrefsMap.getStringAsInt("system_ui_status_bar_icon_data_saver", 0) != 0); // 移动网络图标 initHook(new MobileNetwork()); // initHook(new BigMobileNetworkType(), false); initHook(new DualRowSignalHook(), mPrefsMap.getBoolean("system_ui_statusbar_network_icon_enable")); initHook(MobileTypeSingleHook.INSTANCE, mPrefsMap.getBoolean("system_ui_statusbar_mobile_type_enable")); initHook(MobileTypeTextCustom.INSTANCE, !Objects.equals(mPrefsMap.getString("system_ui_status_bar_mobile_type_custom", ""), "")); // 电池相关 boolean isHideBatteryIcon = mPrefsMap.getBoolean("system_ui_status_bar_battery_icon") || mPrefsMap.getBoolean("system_ui_status_bar_battery_percent") || mPrefsMap.getBoolean("system_ui_status_bar_battery_percent_mark") || mPrefsMap.getBoolean("system_ui_status_bar_battery_charging"); initHook(HideBatteryIcon.INSTANCE, isHideBatteryIcon); initHook(BatteryStyle.INSTANCE, mPrefsMap.getBoolean("system_ui_status_bar_battery_style_enable_custom") || mPrefsMap.getBoolean("system_ui_status_bar_battery_style_change_location")); // initHook(new BatteryIndicator(), mPrefsMap.getBoolean("system_ui_status_bar_battery_indicator_enable")); // 网速指示器 if (mPrefsMap.getBoolean("system_ui_statusbar_network_speed_enable_custom")) { initHook(NetworkSpeed.INSTANCE, !isMoreAndroidVersion(34)); initHook(NetworkSpeedWidth.INSTANCE, mPrefsMap.getInt("system_ui_statusbar_network_speed_fixedcontent_width", 10) > 10); } initHook(NetworkSpeedStyle.INSTANCE); initHook(NetworkSpeedSpacing.INSTANCE, mPrefsMap.getInt("system_ui_statusbar_network_speed_update_spacing", 3) != 3); initHook(NetworkSpeedSec.INSTANCE, mPrefsMap.getBoolean("system_ui_statusbar_network_speed_sec_unit")); initHook(StatusBarNoNetSpeedSep.INSTANCE, mPrefsMap.getBoolean("system_ui_status_bar_no_netspeed_separator")); // 时钟指示器 initHook(TimeStyle.INSTANCE); initHook(TimeCustomization.INSTANCE, mPrefsMap.getStringAsInt("system_ui_statusbar_clock_mode", 0) != 0); // 硬件指示器 initHook(new DisplayHardwareDetail(), mPrefsMap.getBoolean("system_ui_statusbar_battery_enable") || mPrefsMap.getBoolean("system_ui_statusbar_temp_enable")); // 居右显示 boolean isWiFiAtLeft = mPrefsMap.getBoolean("system_ui_status_bar_wifi_at_left"); boolean isMobileNetworkAtLeft = mPrefsMap.getBoolean("system_ui_status_bar_mobile_network_at_left"); boolean isNetworkSpeedAtRight = mPrefsMap.getBoolean("system_ui_status_bar_network_speed_at_right"); boolean isAlarmClockAtRight = mPrefsMap.getBoolean("system_ui_status_bar_alarm_clock_at_right"); boolean isNFCAtRight = mPrefsMap.getBoolean("system_ui_status_bar_nfc_at_right"); boolean isVolumeAtRight = mPrefsMap.getBoolean("system_ui_status_bar_volume_at_right"); boolean isZenAtRight = mPrefsMap.getBoolean("system_ui_status_bar_zen_at_right"); boolean isSwapWiFiAndMobileNetwork = mPrefsMap.getBoolean("system_ui_status_bar_swap_wifi_and_mobile_network"); boolean isStatusBarIconAtRightEnable = isWiFiAtLeft || isMobileNetworkAtLeft || isSwapWiFiAndMobileNetwork || isNetworkSpeedAtRight || isAlarmClockAtRight || isNFCAtRight || isVolumeAtRight || isZenAtRight; initHook(new StatusBarIconPositionAdjust(), isStatusBarIconAtRightEnable); // 导航栏 initHook(HandleLineCustom.INSTANCE, mPrefsMap.getBoolean("system_ui_navigation_handle_custom")); initHook(new NavigationCustom(), mPrefsMap.getBoolean("system_ui_navigation_custom")); initHook(new HideNavigationBar(), mPrefsMap.getBoolean("system_ui_hide_navigation_bar")); // 状态栏布局 initHook(StatusBarLayout.INSTANCE, mPrefsMap.getBoolean("system_ui_statusbar_layout_compatibility_mode") || mPrefsMap.getStringAsInt("system_ui_statusbar_layout_mode", 0) != 0); // 实验性功能 // initHook(new SwitchControlPanel(), false); // initHook(new MiuiGxzwSize(), false); // 控制中心 // initHook(new SmartHome(), false); initHook(new QSDetailBackGround(), mPrefsMap.getInt("system_control_center_qs_detail_bg", 0) > 0); initHook(new GmsTile(), mPrefsMap.getBoolean("security_center_gms_open")); initHook(new FiveGTile(), mPrefsMap.getBoolean("system_control_center_5g_tile")); initHook(new FlashLight(), mPrefsMap.getBoolean("security_flash_light")); initHook(new SunlightMode(), mPrefsMap.getStringAsInt("system_control_center_sunshine_new_mode", 0) != 0); initHook(new QSGridLabels(), mPrefsMap.getInt("system_control_center_old_qs_row", 1) > 1 || mPrefsMap.getBoolean("system_control_center_qs_tile_label")); initHook(new MuteVisibleNotifications(), mPrefsMap.getBoolean("system_ui_control_center_mute_visible_notice")); initHook(new SwitchCCAndNotification(), mPrefsMap.getBoolean("system_ui_control_center_switch_cc_and_notification")); initHook(QSControlDetailBackgroundAlpha.INSTANCE, mPrefsMap.getInt("system_ui_control_center_control_detail_background_alpha", 255) != 255); initHook(FixMediaControlPanel.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_fix_media_control_panel")); initHook(NotificationWeather.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(NotificationWeatherOld.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(NotificationWeatherNew.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_show_weather")); initHook(CompactNotificationsHook.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_compact_notice")); initHook(CCGrid.INSTANCE, mPrefsMap.getInt("system_control_center_cc_rows", 4) > 4 || mPrefsMap.getInt("system_control_center_cc_columns", 4) > 4 || mPrefsMap.getBoolean("system_ui_control_center_rounded_rect") || mPrefsMap.getBoolean("system_control_center_qs_tile_label")); if (isMoreAndroidVersion(33)) { initHook(new QSGrid(), mPrefsMap.getBoolean("system_control_center_old_enable")); initHook(new QQSGrid(), mPrefsMap.getBoolean("system_control_center_old_enable")); } else { initHook(new QSGridOld(), mPrefsMap.getBoolean("system_control_center_old_enable_1")); initHook(new QQSGridOld(), mPrefsMap.getBoolean("system_control_center_old_enable_1")); } initHook(new AutoCollapse(), mPrefsMap.getBoolean("system_ui_control_auto_close")); initHook(RedirectToNotificationChannelSetting.INSTANCE, mPrefsMap.getBoolean("system_ui_control_center_redirect_notice")); initHook(ControlCenterStyle.INSTANCE, mPrefsMap.getBoolean("system_control_center_unlock_old")); // Actions initHook(new StatusBarActions()); // Other initHook(new NotificationFix(), mPrefsMap.getBoolean("system_ui_other_notification_fix")); // 锁屏 initHook(new ScramblePIN(), mPrefsMap.getBoolean("system_ui_lock_screen_scramble_pin")); initHook(ClockDisplaySeconds.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_show_second")); initHook(ChargingCVP.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_show_charging_cv")); initHook(RemoveCamera.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_hide_camera")); initHook(RemoveSmartScreen.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_hide_smart_screen")); initHook(NoPassword.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_password_free")); initHook(LockScreenDoubleTapToSleep.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_double_lock")); initHook(ForceClockUseSystemFontsHook.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_force_system_fonts")); initHook(HideLockscreenZenMode.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_not_disturb_mode")); initHook(HideLockScreenHint.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_unlock_tip")); initHook(HideLockScreenStatusBar.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_hide_status_bar")); if (!isAndroidR()) { initHook(AddBlurEffectToLockScreen.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_blur_button")); initHook(AddBlurEffectToNotificationView.INSTANCE, mPrefsMap.getBoolean("n_enable")); initHook(BlurButton.INSTANCE, mPrefsMap.getBoolean("system_ui_lock_screen_blur_button")); } initHook(DoubleTapToSleep.INSTANCE, mPrefsMap.getBoolean("system_ui_status_bar_double_tap_to_sleep")); initHook(new PluginHelper()); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/ThemeManager.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.thememanager.DisableThemeAdNew; import com.sevtinge.cemiuiler.module.hook.thememanager.EnableFoldTheme; import com.sevtinge.cemiuiler.module.hook.thememanager.EnablePadTheme; import com.sevtinge.cemiuiler.module.hook.thememanager.VersionCodeModify; public class ThemeManager extends BaseModule { @Override public void handleLoadPackage() { initHook(new DisableThemeAdNew(), mPrefsMap.getBoolean("various_theme_diable_ads")); initHook(new EnablePadTheme(), mPrefsMap.getBoolean("various_theme_enable_pad_theme")); initHook(new EnableFoldTheme(), mPrefsMap.getBoolean("various_theme_enable_fold_theme")); // 修改版本号 initHook(new VersionCodeModify(), mPrefsMap.getBoolean("theme_manager_version_code_modify")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/TsmClient.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.tsmclient.AutoNfc; public class TsmClient extends BaseModule { @Override public void handleLoadPackage() { initHook(AutoNfc.INSTANCE, mPrefsMap.getBoolean("tsmclient_auto_nfc")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Updater.java ================================================ package com.sevtinge.cemiuiler.module.app; import android.text.TextUtils; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.updater.DeviceModify; import com.sevtinge.cemiuiler.module.hook.updater.VabUpdate; import com.sevtinge.cemiuiler.module.hook.updater.VersionCodeModify; import com.sevtinge.cemiuiler.module.hook.updater.VersionCodeNew; public class Updater extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); if (mPrefsMap.getStringAsInt("updater_version_mode", 1) != 1) { initHook(VersionCodeNew.INSTANCE); } else { initHook(new VersionCodeModify(), !TextUtils.isEmpty(mPrefsMap.getString("various_updater_miui_version", ""))); } initHook(new VabUpdate(), mPrefsMap.getBoolean("updater_fuck_vab")); initHook(DeviceModify.INSTANCE, !TextUtils.isEmpty(mPrefsMap.getString("updater_device", ""))); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Various.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.various.CollapseMiuiTitle; import com.sevtinge.cemiuiler.module.hook.various.DialogCustom; import com.sevtinge.cemiuiler.module.hook.various.MiuiAppNoOverScroll; import com.sevtinge.cemiuiler.module.hook.various.UnlockIme; import java.util.Arrays; import java.util.HashSet; public class Various extends BaseModule { Class mHelpers; String mPackageName; boolean isMiuiApps; @Override public void handleLoadPackage() { mPackageName = mLoadPackageParam.packageName; isMiuiApps = mPackageName.startsWith("com.miui") || mPackageName.startsWith("com.xiaomi") || miuiDialogCustomApps.contains(mPackageName); initHook(new MiuiAppNoOverScroll(), isMiuiOverScrollApps()); initHook(new DialogCustom(), isMiuiDialogCustom()); initHook(new CollapseMiuiTitle(), isCollapseMiuiTitleApps()); initHook(UnlockIme.INSTANCE, mPrefsMap.getBoolean("various_unlock_ime")); } private boolean isMiuiOverScrollApps() { return mPrefsMap.getBoolean("various_no_overscroll") && miuiOverScrollApps.contains(mPackageName); } private boolean isMiuiDialogCustom() { return mPrefsMap.getStringAsInt("various_dialog_gravity", 0) != 0 && isMiuiApps; } private boolean isCollapseMiuiTitleApps() { return mPrefsMap.getStringAsInt("various_collapse_miui_title", 0) != 0 && collapseMiuiTitleApps.contains(mPackageName); } HashSet miuiOverScrollApps = new HashSet<>(Arrays.asList( "com.android.fileexplorer", "com.android.providers.downloads.ui", "com.android.settings" )); HashSet miuiDialogCustomApps = new HashSet<>(Arrays.asList( "com.android.fileexplorer", "com.android.providers.downloads.ui", "com.android.settings" )); HashSet collapseMiuiTitleApps = new HashSet<>(Arrays.asList( "com.android.fileexplorer", "com.android.providers.downloads.ui", "com.android.settings" )); } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/VoiceAssist.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.base.CloseHostDir; import com.sevtinge.cemiuiler.module.base.LoadHostDir; import com.sevtinge.cemiuiler.module.hook.voiceassist.UseThirdPartyBrowser; public class VoiceAssist extends BaseModule { @Override public void handleLoadPackage() { // dexKit load initHook(LoadHostDir.INSTANCE); initHook(UseThirdPartyBrowser.INSTANCE, mPrefsMap.getBoolean("content_extension_browser")); // dexKit finish initHook(CloseHostDir.INSTANCE); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/app/Weather.java ================================================ package com.sevtinge.cemiuiler.module.app; import com.sevtinge.cemiuiler.module.base.BaseModule; import com.sevtinge.cemiuiler.module.hook.weather.SetDeviceLevel; public class Weather extends BaseModule { @Override public void handleLoadPackage() { initHook(new SetDeviceLevel(), mPrefsMap.getStringAsInt("weather_device_level", 0) != 3); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/base/BaseHook.java ================================================ package com.sevtinge.cemiuiler.module.base; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import com.sevtinge.cemiuiler.BuildConfig; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.utils.PrefsMap; import com.sevtinge.cemiuiler.utils.ResourcesHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils.*; import java.lang.reflect.Field; import java.lang.reflect.Method; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; public abstract class BaseHook { public String TAG = getClass().getSimpleName(); private static final boolean isDebugVersion = BuildConfig.BUILD_TYPE.contains("debug"); private static final boolean isNotReleaseVersion = !BuildConfig.BUILD_TYPE.contains("release"); private final boolean detailLog = !mPrefsMap.getBoolean("settings_disable_detailed_log"); public LoadPackageParam lpparam; public static final ResourcesHook mResHook = XposedInit.mResHook; public static final PrefsMap mPrefsMap = XposedInit.mPrefsMap; public static final String ACTION_PREFIX = "com.sevtinge.cemiuiler.module.action."; public abstract void init(); public void onCreate(LoadPackageParam lpparam) { try { setLoadPackageParam(lpparam); init(); if (detailLog && isNotReleaseVersion) { XposedLogUtils.logI(TAG, "Hook Success."); } } catch (Throwable t) { XposedLogUtils.logE(TAG, "Hook Failed", t); } } public void setLoadPackageParam(LoadPackageParam param) { lpparam = param; } public Class findClass(String className) { return findClass(className, lpparam.classLoader); } public Class findClass(String className, ClassLoader classLoader) { return XposedHelpers.findClass(className, classLoader); } public Class findClassIfExists(String className) { try { return findClass(className); } catch (XposedHelpers.ClassNotFoundError e) { LogD("findClassIfExists", "find " + className + " is Null", e); return null; } } public Class findClassIfExists(String newClassName, String oldClassName) { try { return findClass(findClassIfExists(newClassName) != null ? newClassName : oldClassName); } catch (XposedHelpers.ClassNotFoundError e) { LogD("findClassIfExists", "find " + newClassName + " and " + oldClassName + " is Null", e); return null; } } public Class findClassIfExists(String className, ClassLoader classLoader) { try { return findClass(className, classLoader); } catch (XposedHelpers.ClassNotFoundError e) { LogD("findClassIfExists", "find " + className + " is Null", e); return null; } } public static class MethodHook extends XC_MethodHook { protected void before(MethodHookParam param) throws Throwable { } protected void after(MethodHookParam param) throws Throwable { } public MethodHook() { super(); } public MethodHook(int priority) { super(priority); } @Override public void beforeHookedMethod(MethodHookParam param) throws Throwable { try { this.before(param); } catch (Throwable t) { LogD("BeforeHook", t); } } @Override public void afterHookedMethod(MethodHookParam param) throws Throwable { try { this.after(param); } catch (Throwable t) { LogD("AfterHook", t); } } } public void findAndHookMethod(Class clazz, String methodName, Object... parameterTypesAndCallback) { XposedHelpers.findAndHookMethod(clazz, methodName, parameterTypesAndCallback); } public void findAndHookMethod(String className, String methodName, Object... parameterTypesAndCallback) { findAndHookMethod(findClassIfExists(className), methodName, parameterTypesAndCallback); } public boolean findAndHookMethodSilently(String className, String methodName, Object... parameterTypesAndCallback) { try { findAndHookMethod(className, methodName, parameterTypesAndCallback); return true; } catch (Throwable t) { LogD("findAndHookMethodSilently", className + methodName + " is null", t); return false; } } public boolean findAndHookMethodSilently(Class clazz, String methodName, Object... parameterTypesAndCallback) { try { findAndHookMethod(clazz, methodName, parameterTypesAndCallback); return true; } catch (Throwable t) { LogD("findAndHookMethodSilently", clazz + methodName + " is null", t); return false; } } public void findAndHookConstructor(String className, Object... parameterTypesAndCallback) { findAndHookConstructor(findClassIfExists(className), parameterTypesAndCallback); } public void findAndHookConstructor(Class hookClass, Object... parameterTypesAndCallback) { XposedHelpers.findAndHookConstructor(hookClass, parameterTypesAndCallback); } public void hookMethod(Method method, MethodHook callback) { XposedBridge.hookMethod(method, callback); } public void hookAllMethods(String className, String methodName, XC_MethodHook callback) { try { Class hookClass = findClassIfExists(className); if (hookClass != null) { XposedBridge.hookAllMethods(hookClass, methodName, callback).size(); } } catch (Throwable t) { LogD("HookAllMethods", className + " is " + methodName + " abnormal", t); } } public void hookAllMethods(Class hookClass, String methodName, XC_MethodHook callback) { try { XposedBridge.hookAllMethods(hookClass, methodName, callback).size(); } catch (Throwable t) { LogD("HookAllMethods", hookClass + " is " + methodName + " abnormal", t); } } public void hookAllMethodsSilently(String className, String methodName, XC_MethodHook callback) { try { Class hookClass = findClassIfExists(className); if (hookClass != null) { XposedBridge.hookAllMethods(hookClass, methodName, callback).size(); } } catch (Throwable ignored) { } } public boolean hookAllMethodsSilently(Class hookClass, String methodName, XC_MethodHook callback) { try { if (hookClass != null) { XposedBridge.hookAllMethods(hookClass, methodName, callback).size(); } return false; } catch (Throwable t) { return false; } } public void hookAllConstructors(String className, MethodHook callback) { try { Class hookClass = findClassIfExists(className); if (hookClass != null) { XposedBridge.hookAllConstructors(hookClass, callback).size(); } } catch (Throwable t) { LogD("hookAllConstructors", className + " is abnormal", t); } } public void hookAllConstructors(Class hookClass, MethodHook callback) { try { XposedBridge.hookAllConstructors(hookClass, callback).size(); } catch (Throwable t) { LogD("hookAllConstructors", hookClass + " is abnormal", t); } } public Object getStaticObjectFieldSilently(Class clazz, String fieldName) { try { return XposedHelpers.getStaticObjectField(clazz, fieldName); } catch (Throwable t) { return null; } } public void setDeclaredField(XC_MethodHook.MethodHookParam param, String iNeedString, Object iNeedTo) { if (param != null) { try { Field setString = param.thisObject.getClass().getDeclaredField(iNeedString); setString.setAccessible(true); try { setString.set(param.thisObject, iNeedTo); Object result = setString.get(param.thisObject); checkLast("getDeclaredField", iNeedString, iNeedTo, result); } catch (IllegalAccessException e) { XposedLogUtils.logW("IllegalAccessException to: " + iNeedString + " need to: " + iNeedTo + " code:" + e); } } catch (NoSuchFieldException e) { XposedLogUtils.logW("No such the: " + iNeedString + " code: " + e); } } else { XposedLogUtils.logW("Param is null Field: " + iNeedString + " to: " + iNeedTo); } } public void checkLast(String setObject, Object fieldName, Object value, Object last) { if (value.equals(last)) { XposedLogUtils.logI(setObject + " Success! set " + fieldName + " to " + value); } else { XposedLogUtils.logW(setObject + " Failed! set " + fieldName + " to " + value + " hope: " + value + " but: " + last); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/base/BaseModule.java ================================================ package com.sevtinge.cemiuiler.module.base; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.utils.PrefsMap; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; public abstract class BaseModule implements IXposedHook { public LoadPackageParam mLoadPackageParam = null; public final PrefsMap mPrefsMap = XposedInit.mPrefsMap; public void init(LoadPackageParam lpparam) { mLoadPackageParam = lpparam; initZygote(); handleLoadPackage(); } @Override public void initZygote() { } public void initHook(BaseHook baseHook) { initHook(baseHook, true); } public void initHook(BaseHook baseHook, boolean isInit) { if (isInit) { baseHook.onCreate(mLoadPackageParam); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/base/BaseXposedInit.java ================================================ package com.sevtinge.cemiuiler.module.base; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import com.sevtinge.cemiuiler.BuildConfig; import com.sevtinge.cemiuiler.module.app.AiAsst; import com.sevtinge.cemiuiler.module.app.Aod; import com.sevtinge.cemiuiler.module.app.Barrage; import com.sevtinge.cemiuiler.module.app.Browser; import com.sevtinge.cemiuiler.module.app.Camera; import com.sevtinge.cemiuiler.module.app.Clock; import com.sevtinge.cemiuiler.module.app.ContentExtension; import com.sevtinge.cemiuiler.module.app.Creation; import com.sevtinge.cemiuiler.module.app.Downloads; import com.sevtinge.cemiuiler.module.app.ExternalStorage; import com.sevtinge.cemiuiler.module.app.FileExplorer; import com.sevtinge.cemiuiler.module.app.Gallery; import com.sevtinge.cemiuiler.module.app.GuardProvider; import com.sevtinge.cemiuiler.module.app.Home; import com.sevtinge.cemiuiler.module.app.InCallUi; import com.sevtinge.cemiuiler.module.app.Joyose; import com.sevtinge.cemiuiler.module.app.Lbe; import com.sevtinge.cemiuiler.module.app.Market; import com.sevtinge.cemiuiler.module.app.MediaEditor; import com.sevtinge.cemiuiler.module.app.MiLink; import com.sevtinge.cemiuiler.module.app.MiSettings; import com.sevtinge.cemiuiler.module.app.MiShare; import com.sevtinge.cemiuiler.module.app.MiWallpaper; import com.sevtinge.cemiuiler.module.app.Mms; import com.sevtinge.cemiuiler.module.app.Mtb; import com.sevtinge.cemiuiler.module.app.Music; import com.sevtinge.cemiuiler.module.app.NetworkBoost; import com.sevtinge.cemiuiler.module.app.Nfc; import com.sevtinge.cemiuiler.module.app.Notes; import com.sevtinge.cemiuiler.module.app.PackageInstaller; import com.sevtinge.cemiuiler.module.app.PersonalAssistant; import com.sevtinge.cemiuiler.module.app.Phone; import com.sevtinge.cemiuiler.module.app.PowerKeeper; import com.sevtinge.cemiuiler.module.app.Scanner; import com.sevtinge.cemiuiler.module.app.ScreenRecorder; import com.sevtinge.cemiuiler.module.app.ScreenShot; import com.sevtinge.cemiuiler.module.app.SecurityCenter; import com.sevtinge.cemiuiler.module.app.Settings; import com.sevtinge.cemiuiler.module.app.SystemFramework; import com.sevtinge.cemiuiler.module.app.SystemSettings; import com.sevtinge.cemiuiler.module.app.SystemUI; import com.sevtinge.cemiuiler.module.app.ThemeManager; import com.sevtinge.cemiuiler.module.app.TsmClient; import com.sevtinge.cemiuiler.module.app.Updater; import com.sevtinge.cemiuiler.module.app.Various; import com.sevtinge.cemiuiler.module.app.VoiceAssist; import com.sevtinge.cemiuiler.module.app.Weather; import com.sevtinge.cemiuiler.module.hook.thememanager.ThemeCrackNew; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.PrefsMap; import com.sevtinge.cemiuiler.utils.PrefsUtils; import com.sevtinge.cemiuiler.utils.ResourcesHook; import com.sevtinge.cemiuiler.utils.ShellUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.io.File; import java.util.Map; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.IXposedHookZygoteInit; import de.robv.android.xposed.XSharedPreferences; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; public abstract class BaseXposedInit implements IXposedHookLoadPackage, IXposedHookZygoteInit { public static ResourcesHook mResHook; public static String mModulePath = null; public static PrefsMap mPrefsMap = new PrefsMap<>(); public final SystemFramework mSystemFramework = new SystemFramework(); public final SystemUI mSystemUI = new SystemUI(); public final Home mHome = new Home(); public final ScreenShot mScreenShot = new ScreenShot(); public final ScreenRecorder mScreenRecorder = new ScreenRecorder(); public final SecurityCenter mSecurityCenter = new SecurityCenter(); public final SystemSettings mSystemSettings = new SystemSettings(); public final Settings mSettings = new Settings(); public final PersonalAssistant mPersonalAssistant = new PersonalAssistant(); public final ThemeManager mThemeManager = new ThemeManager(); public final Updater mUpdater = new Updater(); public final Market mMarket = new Market(); public final MediaEditor mMediaEditor = new MediaEditor(); public final PackageInstaller mPackageInstaller = new PackageInstaller(); public final PowerKeeper mPowerKeeper = new PowerKeeper(); public final MiSettings mMiSettings = new MiSettings(); public final Joyose mJoyose = new Joyose(); public final Various mVarious = new Various(); public final Weather mWeather = new Weather(); public final Clock mClock = new Clock(); public final FileExplorer mFileExplorer = new FileExplorer(); public final Music mMusic = new Music(); public final Gallery mGallery = new Gallery(); public final AiAsst mAiAsst = new AiAsst(); public final Scanner mScanner = new Scanner(); public final MiShare mMiShare = new MiShare(); public final MiLink mMiLink = new MiLink(); public final GuardProvider mGuardProvider = new GuardProvider(); public final Lbe mLbe = new Lbe(); public final InCallUi mInCallUi = new InCallUi(); public final TsmClient mTsmClient = new TsmClient(); public final ContentExtension mContentExtension = new ContentExtension(); public final VoiceAssist mVoiceAssist = new VoiceAssist(); public final Mms mMms = new Mms(); public final ExternalStorage mExternalStorage = new ExternalStorage(); public final Camera mCamera = new Camera(); public final Browser mBrowser = new Browser(); public final Mtb mMtb = new Mtb(); public final Phone mPhone = new Phone(); public final MiWallpaper mMiWallpaper = new MiWallpaper(); public final Downloads mDownloads = new Downloads(); public final Aod mAod = new Aod(); public final Barrage mBarrage = new Barrage(); public final Notes mNotes = new Notes(); public final NetworkBoost networkBoost = new NetworkBoost(); public final Creation mCreation = new Creation(); public final Nfc mNfc = new Nfc(); @Override public void initZygote(StartupParam startupParam) throws Throwable { setXSharedPrefs(); mResHook = new ResourcesHook(); mModulePath = startupParam.modulePath; } public void setXSharedPrefs() { if (mPrefsMap.size() == 0) { XSharedPreferences mXSharedPreferences; try { mXSharedPreferences = new XSharedPreferences(Helpers.mAppModulePkg, PrefsUtils.mPrefsName); mXSharedPreferences.makeWorldReadable(); Map allPrefs = mXSharedPreferences == null ? null : mXSharedPreferences.getAll(); if (allPrefs == null || allPrefs.size() == 0) { mXSharedPreferences = new XSharedPreferences(new File(PrefsUtils.mPrefsFile)); mXSharedPreferences.makeWorldReadable(); allPrefs = mXSharedPreferences == null ? null : mXSharedPreferences.getAll(); if (allPrefs == null || allPrefs.size() == 0) { XposedLogUtils.logE( "[UID" + android.os.Process.myUid() + "]", "Cannot read module's SharedPreferences, some mods might not work!" ); } else { mPrefsMap.putAll(allPrefs); } } else { mPrefsMap.putAll(allPrefs); } } catch (Throwable t) { LogD("setXSharedPrefs", t); } } } public void init(LoadPackageParam lpparam) { String packageName = lpparam.packageName; switch (packageName) { case "android" -> { mSystemFramework.init(lpparam); mVarious.init(lpparam); } case "com.android.systemui" -> { if (isSystemUIModuleEnable()) { mSystemUI.init(lpparam); mVarious.init(lpparam); } } case "com.miui.home" -> { if (isHomeModuleEnable()) { mHome.init(lpparam); mVarious.init(lpparam); } } case "com.miui.securitycenter" -> { if (isSecurityCenterModuleEnable()) { mSecurityCenter.init(lpparam); mVarious.init(lpparam); } } case "com.android.settings" -> { mSystemSettings.init(lpparam); mSettings.init(lpparam); mVarious.init(lpparam); } case "com.miui.personalassistant" -> { mPersonalAssistant.init(lpparam); mVarious.init(lpparam); } case "com.android.thememanager" -> { new ThemeCrackNew().init(lpparam); mThemeManager.init(lpparam); mVarious.init(lpparam); } case "com.android.browser" -> { mBrowser.init(lpparam); mVarious.init(lpparam); } case "com.android.nfc" -> { mNfc.init(lpparam); mVarious.init(lpparam); } case "com.android.updater" -> { mUpdater.init(lpparam); mVarious.init(lpparam); } case "com.xiaomi.market" -> mMarket.init(lpparam); case "com.miui.packageinstaller" -> { mPackageInstaller.init(lpparam); mVarious.init(lpparam); } case "com.miui.powerkeeper" -> mPowerKeeper.init(lpparam); case "com.xiaomi.misettings" -> { mMiSettings.init(lpparam); mVarious.init(lpparam); } case "com.xiaomi.joyose" -> mJoyose.init(lpparam); case "com.miui.screenshot" -> mScreenShot.init(lpparam); case "com.miui.screenrecorder" -> { mScreenRecorder.init(lpparam); mVarious.init(lpparam); } case "com.miui.mediaeditor" -> mMediaEditor.init(lpparam); case "com.miui.miwallpaper" -> { mMiWallpaper.init(lpparam); mVarious.init(lpparam); } case "com.miui.weather2" -> { mWeather.init(lpparam); mVarious.init(lpparam); } case "com.android.deskclock" -> { mClock.init(lpparam); mVarious.init(lpparam); } case "com.miui.player" -> mMusic.init(lpparam); case "com.miui.gallery" -> { mGallery.init(lpparam); mVarious.init(lpparam); } case "com.miui.aod" -> { mAod.init(lpparam); mVarious.init(lpparam); } case "com.xiaomi.barrage" -> mBarrage.init(lpparam); case "com.xiaomi.aiasst.vision" -> { mAiAsst.init(lpparam); mVarious.init(lpparam); } case "com.xiaomi.scanner" -> { mScanner.init(lpparam); mVarious.init(lpparam); } case "com.miui.mishare.connectivity" -> { mMiShare.init(lpparam); mVarious.init(lpparam); } case "com.milink.service" -> mMiLink.init(lpparam); case "com.miui.guardprovider" -> mGuardProvider.init(lpparam); case "com.lbe.security.miui" -> { mLbe.init(lpparam); mVarious.init(lpparam); } case "com.android.incallui" -> { mInCallUi.init(lpparam); mVarious.init(lpparam); } case "com.miui.notes" -> { mNotes.init(lpparam); mVarious.init(lpparam); } case "com.miui.tsmclient" -> { mTsmClient.init(lpparam); mVarious.init(lpparam); } case "com.miui.contentextension" -> { mContentExtension.init(lpparam); mVarious.init(lpparam); } case "com.miui.voiceassist" -> { mVoiceAssist.init(lpparam); mVarious.init(lpparam); } case "com.android.mms" -> { mMms.init(lpparam); mVarious.init(lpparam); } case "com.android.fileexplorer" -> { mFileExplorer.init(lpparam); mVarious.init(lpparam); } case "com.android.phone" -> mPhone.init(lpparam); case "com.xiaomi.mtb" -> mMtb.init(lpparam); case "com.android.externalstorage" -> { mExternalStorage.init(lpparam); mVarious.init(lpparam); } case "com.android.camera" -> { mCamera.init(lpparam); mVarious.init(lpparam); } case "com.android.providers.downloads" -> mDownloads.init(lpparam); case "com.miui.creation" -> { mCreation.init(lpparam); mVarious.init(lpparam); } case "com.xiaomi.NetworkBoost" -> networkBoost.init(lpparam); case BuildConfig.APPLICATION_ID -> { ModuleActiveHook(lpparam); XSharedPreferences mXSharedPreferences = new XSharedPreferences(Helpers.mAppModulePkg, PrefsUtils.mPrefsName); String sharedPreferencePath = mXSharedPreferences.getFile().getPath(); sharedPreferencePath = sharedPreferencePath.replace("/com.sevtinge.cemiuiler/cemiuiler_prefs.xml", ""); XposedLogUtils.logD(sharedPreferencePath); File folder = new File(sharedPreferencePath+"/com.sevtinge.hyperceiler"); if (folder.exists() && folder.isDirectory()) { ShellUtils.execCommand("dd if="+sharedPreferencePath+"/com.sevtinge.cemiuiler/cemiuiler_prefs.xml of="+sharedPreferencePath+"/com.sevtinge.hyperceiler/hyperceiler_prefs.xml", true, false); } else { ShellUtils.execCommand("mkdir "+sharedPreferencePath+"/com.sevtinge.hyperceiler", true, false); } ShellUtils.execCommand("dd if="+sharedPreferencePath+"/com.sevtinge.cemiuiler/cemiuiler_prefs.xml of="+sharedPreferencePath+"/com.sevtinge.hyperceiler/hyperceiler_prefs.xml", true, false); } default -> mVarious.init(lpparam); } } public void ModuleActiveHook(LoadPackageParam lpparam) { Class mHelpers = XposedHelpers.findClassIfExists(Helpers.mAppModulePkg + ".utils.Helpers", lpparam.classLoader); XposedHelpers.setStaticBooleanField(mHelpers, "isModuleActive", true); XposedHelpers.setStaticIntField(mHelpers, "XposedVersion", XposedBridge.getXposedVersion()); } public boolean isSafeModeEnable(String key) { return !mPrefsMap.getBoolean(key); } public boolean isSystemUIModuleEnable() { return isSafeModeEnable("system_ui_safe_mode_enable"); } public boolean isHomeModuleEnable() { return isSafeModeEnable("home_safe_mode_enable"); } public boolean isSecurityCenterModuleEnable() { return isSafeModeEnable("security_center_safe_mode_enable"); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/base/HostDir.kt ================================================ package com.sevtinge.cemiuiler.module.base import com.sevtinge.cemiuiler.utils.DexKit.closeDexKit import com.sevtinge.cemiuiler.utils.DexKit.initDexKit object LoadHostDir : BaseHook() { override fun init() { if (lpparam != null) { initDexKit(lpparam) } } } object CloseHostDir : BaseHook() { override fun init() { if (lpparam != null) { closeDexKit() } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/base/IXposedHook.java ================================================ package com.sevtinge.cemiuiler.module.base; public interface IXposedHook { void initZygote(); void handleLoadPackage(); } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/aiasst/AiCaptions.kt ================================================ package com.sevtinge.cemiuiler.module.hook.aiasst import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class AiCaptions : BaseHook() { override fun init() { val finder = loadClass("com.xiaomi.aiasst.vision.utils.SupportAiSubtitlesUtils").methodFinder() finder.filterByName("isSupportAiSubtitles").first() .createHook { returnConstant(true) } finder.filterByName("isSupportJapanKoreaTranslation").first() .createHook { returnConstant(true) } finder.filterByName("deviceWhetherSupportOfflineSubtitles").first() .createHook { returnConstant(true) } finder.filterByName("isSupportOfflineAiSubtitles").first() .createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/aod/UnlockAlwaysOnDisplay.kt ================================================ package com.sevtinge.cemiuiler.module.hook.aod import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object UnlockAlwaysOnDisplay : BaseHook() { override fun init() { loadClass("com.miui.aod.widget.AODSettings").methodFinder().first { name == "onlySupportKeycodeGoto" }.createHook { returnConstant(false) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/barrage/AnyBarrage.kt ================================================ package com.sevtinge.cemiuiler.module.hook.barrage import android.service.notification.StatusBarNotification import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.ObjectUtils.getObjectOrNullAs import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object AnyBarrage : BaseHook() { override fun init() { loadClass("com.xiaomi.barrage.service.NotificationMonitorService").methodFinder() .filterByName("filterNotification") .first().createHook { before { param -> val statusBarNotification = param.args[0] as StatusBarNotification getObjectOrNullAs>( param.thisObject, "mBarragePackageList" )!!.let { if (!it.contains(statusBarNotification.packageName)) { it.add(statusBarNotification.packageName) } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/barrage/CustomBarrageLength.kt ================================================ package com.sevtinge.cemiuiler.module.hook.barrage import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook //from StarVoyager by @hosizoraru object CustomBarrageLength : BaseHook() { private val barrageLength by lazy { mPrefsMap.getInt("barrage_length", 36) } override fun init() { val clazzString = loadClass("java.lang.String") clazzString.methodFinder() .filterByName("subSequence") .filterByParamCount(2) .first().createHook { before { param -> if (Throwable().stackTrace.any { it.className == "com.xiaomi.barrage.utils.BarrageWindowUtils" }) { param.args[1] = minOf(barrageLength, (param.thisObject as String).length) } } after { if (it.throwable != null) { it.throwable = null it.result = it.thisObject } } } clazzString.methodFinder() .filterByName("length") .filterByParamCount(0) .first().createHook { after { param -> val stacktrace = Throwable().stackTrace if (stacktrace.any { it.className in setOf( "java.lang.String", "android.text.SpannableStringBuilder" ) }) return@after if (stacktrace.any { it.className == "com.xiaomi.barrage.utils.BarrageWindowUtils" && it.methodName in setOf( "addBarrageNotification", "sendBarrage" ) }) { val realResult = (param.result as Int) param.result = if (barrageLength < 36) { if (realResult > barrageLength) { maxOf(37, realResult) } else realResult } else { if (realResult <= barrageLength) { minOf(35, realResult) } else realResult } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/browser/DebugMode.kt ================================================ package com.sevtinge.cemiuiler.module.hook.browser import com.github.kyuubiran.ezxhelper.EzXHelper.safeClassLoader import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.closeDexKit import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.DexKit.initDexKit import com.sevtinge.cemiuiler.utils.Helpers.getPackageVersionCode import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedBridge object DebugMode : BaseHook() { private var found = false override fun init() { /* val result: List = Objects.requireNonNull(mBrowserResultMethodsMap.get("DebugMode")) for (descriptor in result) { val DebugMode: Method = descriptor.getMethodInstance(lpparam.classLoader) if (DebugMode.returnType == Boolean::class.javaPrimitiveType && DebugMode.toString() .contains("getDebugMode") ) { log("DebugMode method is $DebugMode") found = true XposedBridge.hookMethod(DebugMode, XC_MethodReplacement.returnConstant(true)) } } if (!found) { val result1: List = Objects.requireNonNull(mBrowserResultMethodsMap.get("DebugMode1")) for (descriptor1 in result1) { val DebugMode1: Method = descriptor1.getMethodInstance(lpparam.classLoader) if (DebugMode1.returnType == Boolean::class.javaPrimitiveType && DebugMode1.toString() .contains("getDebugMode") ) { log("DebugMode1 method is $DebugMode1") found = true XposedBridge.hookMethod( DebugMode1, XC_MethodReplacement.returnConstant(true) ) } } } if (!found) { val result2: List = Objects.requireNonNull(mBrowserResultMethodsMap.get("DebugMode2")) for (descriptor2 in result2) { val DebugMode2: Method = descriptor2.getMethodInstance(lpparam.classLoader) if (DebugMode2.returnType == Boolean::class.javaPrimitiveType && DebugMode2.toString() .contains("getDebugMode") ) { log("DebugMode2 method is $DebugMode2") XposedBridge.hookMethod( DebugMode2, XC_MethodReplacement.returnConstant(true) ) } } }*/ initDexKit(lpparam) dexKitBridge.findMethod { matcher { addUsingStringsEquals("pref_key_debug_mode_new") returnType = "boolean" } }.forEach { val debugMode = it.getMethodInstance(lpparam.classLoader) if (debugMode.toString().contains("getDebugMode")) { XposedLogUtils.logI("DebugMode method is $debugMode") found = true XposedBridge.hookMethod( debugMode, XC_MethodReplacement.returnConstant(true) ) } } if (!found) { dexKitBridge.findMethod { matcher { addUsingStringsEquals("pref_key_debug_mode") returnType = "boolean" } }.forEach { val debugMode1 = it.getMethodInstance(safeClassLoader) if (debugMode1.toString().contains("getDebugMode")) { XposedLogUtils.logI("DebugMode1 method is $debugMode1") found = true XposedBridge.hookMethod( debugMode1, XC_MethodReplacement.returnConstant(true) ) } } } if (!found) { dexKitBridge.findMethod { matcher { addUsingStringsEquals("pref_key_debug_mode_" + getPackageVersionCode(lpparam)) returnType = "boolean" } }.forEach { val debugMode2 = it.getMethodInstance(lpparam.classLoader) if (debugMode2.toString().contains("getDebugMode")) { XposedLogUtils.logI("DebugMode2 method is $debugMode2") found = true XposedBridge.hookMethod( debugMode2, XC_MethodReplacement.returnConstant(true) ) } } } closeDexKit() } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/EnableLabOptions.kt ================================================ package com.sevtinge.cemiuiler.module.hook.camera import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.hookBeforeMethod import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object EnableLabOptions : BaseHook() { override fun init() { try { "com.xiaomi.camera.util.SystemProperties".hookBeforeMethod( "getBoolean", String::class.java, Boolean::class.java ) { if (it.args[0] == "camera.lab.options") it.result = true } } catch (e: Exception) { XposedLogUtils.logE(TAG, e) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/Unlock120Fps.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class Unlock120Fps extends BaseHook { @Override public void init() { hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupported4K120Fps", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/Unlock60Fps.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class Unlock60Fps extends BaseHook { @Override public void init() { hookAllMethods("com.android.camera.data.data.config.ComponentConfigVideoQuality", "isSupport60FPS", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockAiEnhance.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockAiEnhance extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "supportAiEnhancedVideo", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "supportAiEnhancedVideo", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockAiShutter.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockAiShutter extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportAiShutter", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportAiShutter", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera.CameraSettings", "isSupportAiShutter", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockAiWatermark.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockAiWatermark extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.aiwatermark.AIWaterModuleEntry", "support", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockAmbilight.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockAmbilight extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.ambilight.AmbilightModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockAudioZoom.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockAudioZoom extends BaseHook { @Override public void init() { hookAllMethods("com.android.camera.aiaudio.AiAudioParameterManager", "isSupportAiAudioNew", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockClone.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockClone extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.clone.CloneModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.android.camera.features.mode.more.clone.MoreCloneModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockColorEnhance.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockColorEnhance extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportedColorEnhance", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportedColorEnhance", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockCosmeticMirror.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockCosmeticMirror extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.cosmeticmirror.CosmeticMirrorModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockCvlens.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; public class UnlockCvlens extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.CameraSettings", "isSupportCvLensDevice", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true); } }); try { findAndHookMethod("com.android.camera.CameraSettings", "getCvLensVersion", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(2); } }); findAndHookMethod("com.android.camera2.CameraCapabilities", "getCvLensVersion", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(2); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "getCvLensVersion", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(2); } }); } catch (Exception e) { XposedLogUtils.logI("try to hook CvLensVersion failed!\n" + e); throw new RuntimeException(e); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockCyberFocusVersion2.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockCyberFocusVersion2 extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isCyberFocusVersion2", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isCyberFocusVersion2", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockDoc.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockDoc extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.doc.DocModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockDualcam.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockDualcam extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.dualcam.DualCamModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockDuration.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockDuration extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.fast.FastMotionModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockFilm.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockFilm extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.more.film.MoreFilmModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockFilmDelay.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockFilmDelay extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.film.delay.LongExpModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockFilmDollyZoom.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockFilmDollyZoom extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.film.dollyzoom.DollyZoomModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockFilmDream.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockFilmDream extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.film.dream.DreamModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockFilmSlowShutter.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockFilmSlowShutter extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.film.slowshutter.SlowShutterModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockFilmTimeBackflow.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockFilmTimeBackflow extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.film.timebackflow.TimeBackflowModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockFilmTimeFreeze.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockFilmTimeFreeze extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.film.timefreeze.TimeFreezeModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockHandGesture.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockHandGesture extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.data.data.runing.DataItemRunning", "supportHandGesture", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockHdr.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockHdr extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportVideoHdr", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportVideoHdr", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportQcomVideoHdr", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportQcomVideoHdr", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockHeic.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockHeic extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isHeicSupported", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isHeicSupported", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockIdcard.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockIdcard extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.idcard.IDCardModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockLog.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockLog extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportedVideoLogFormat", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportedVideoLogFormat", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockMakeup.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockMakeup extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportMakeups", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportMakeups2", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportMakeups", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportMakeups2", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockMenMakeup.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockMenMakeup extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportMaleMakeupSwitch", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportMaleMakeupSwitch", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockMilive.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockMilive extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.milive.MiLiveModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockMoon.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockMoon extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.moon.MoonModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockNevus.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockNevus extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportNevusWipeSwitch", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportNevusSupported", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportNevusWipeSwitch", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockNewBeauty.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockNewBeauty extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportPortraitBeautyItem", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportPortraitBeautyItem", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockPano.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockPano extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.pano.pano3.PanoModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockPixel.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockPixel extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.pixel.PixelModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockPortrait.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockPortrait extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.portrait.PortraitModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockRaw.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockRaw extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportRaw", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportRaw", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockSlow.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockSlow extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.slow.SlowMotionModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockTrackEyes.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockTrackEyes extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportTrackEye", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportTrackEye", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockTrackFeature.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockTrackFeature extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportTrackFeatureEnable", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportTrackFeatureEnable", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockTrackFocus.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockTrackFocus extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera2.CameraCapabilities", "isSupportTrackFocus", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.android.camera2.CameraCapabilities", "isTrackFocusDefined", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.android.camera2.CameraCapabilitiesUtil", "isSupportTrackFocus", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockVideosky.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockVideosky extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.videosky.VideoSkyModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockVlog.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockVlog extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.vlog.VlogModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.android.camera.features.mode.more.vlog.MoreVVModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/camera/UnlockVlogPro.java ================================================ package com.sevtinge.cemiuiler.module.hook.camera; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockVlogPro extends BaseHook { @Override public void init() { findAndHookMethod("com.android.camera.features.mode.vlogpro.VlogProModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.android.camera.features.mode.more.vlogpro.MoreVlogProModuleEntry", "support", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/clock/EnableHourGlass.java ================================================ package com.sevtinge.cemiuiler.module.hook.clock; import static com.sevtinge.cemiuiler.utils.Helpers.getPackageVersionCode; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; public class EnableHourGlass extends BaseHook { @Override public void init() { int appVersionCode = getPackageVersionCode(lpparam); hookAllMethods("com.android.deskclock.util.Util", "isHourGlassEnable", new MethodHook() { @Override protected void before(MethodHookParam param) { if (appVersionCode <= 130206400) { param.setResult(true); } else { XposedLogUtils.logI("Your clock versionCode is " + appVersionCode); XposedLogUtils.logI("Please revert to a supported version yourself"); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/contentextension/DoublePress.kt ================================================ package com.sevtinge.cemiuiler.module.hook.contentextension import android.content.Context import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class DoublePress : BaseHook() { override fun init() { loadClass("com.miui.contentextension.utils.ContentCatcherUtil").methodFinder().first { name == "isCatcherSupportDoublePress" && parameterTypes[0] == Context::class.java }.createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/contentextension/HorizontalContentExtension.kt ================================================ package com.sevtinge.cemiuiler.module.hook.contentextension import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object HorizontalContentExtension : BaseHook() { override fun init() { loadClass("com.miui.contentextension.services.TextContentExtensionService").methodFinder() .first { name == "isScreenPortrait" }.createHook { after { it.result = true } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/contentextension/LinkOpenMode.java ================================================ package com.sevtinge.cemiuiler.module.hook.contentextension; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.text.TextUtils; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.List; import de.robv.android.xposed.XposedHelpers; public class LinkOpenMode extends BaseHook { Class mAppsUtils; @Override public void init() { mAppsUtils = findClassIfExists("com.miui.contentextension.utils.AppsUtils"); int mode = mPrefsMap.getStringAsInt("content_extension_link_open_mode", 0); hookAllMethods(mAppsUtils, "generateOpenIntent", new MethodHook() { @Override protected void before(MethodHookParam param) { Context mContext = (Context) param.args[0]; Object o = param.args[1]; String detailUrl = (String) XposedHelpers.callMethod(o, "getIntent"); if (TextUtils.isEmpty(detailUrl)) { detailUrl = (String) XposedHelpers.callMethod(o, "getDetailUrl"); } Uri uri = Uri.parse(detailUrl); setOpenIntent(mContext, uri, mode); param.setResult(null); } }); } private void setOpenIntent(Context context, Uri uri, int mode) { Intent intent = new Intent(Intent.ACTION_VIEW, uri); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); switch (mode) { case 0 -> setFreeFormIntent(context, getDefaultBrowserApp(context)); case 2 -> { intent.setPackage("com.android.browser"); setFreeFormIntent(context, "com.android.browser"); } } context.startActivity(intent); } private void setFreeFormIntent(Context context, String packageName) { if (mPrefsMap.getBoolean("system_framework_freeform_jump") && mPrefsMap.getBoolean("system_framework_freeform_content_extension")) { Intent mFreeFormIntent = new Intent(ACTION_PREFIX + "SetFreeFormPackage"); mFreeFormIntent.putExtra("package", packageName); context.sendBroadcast(mFreeFormIntent); } } private String getDefaultBrowserApp(Context context) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.addCategory(Intent.CATEGORY_BROWSABLE); Uri uri = Uri.parse("http://"); intent.setDataAndType(uri, null); List resolveInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.GET_INTENT_FILTERS); if (resolveInfoList.size() > 0) { ActivityInfo activityInfo = resolveInfoList.get(0).activityInfo; return activityInfo.packageName; } else { return null; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/contentextension/SuperImage.kt ================================================ package com.sevtinge.cemiuiler.module.hook.contentextension import android.graphics.Bitmap import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class SuperImage : BaseHook() { override fun init() { loadClass("com.miui.contentextension.utils.SuperImageUtils").methodFinder().first { name == "isSupportSuperImage" }.createHook { returnConstant(true) } loadClass("com.miui.contentextension.utils.SuperImageUtils").methodFinder().first { name == "isBitmapSupportSuperImage" && parameterTypes[0] == Bitmap::class.java }.createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/contentextension/UnlockTaplus.kt ================================================ package com.sevtinge.cemiuiler.module.hook.contentextension import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.ClassUtils.setStaticObject import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.IS_TABLET object UnlockTaplus : BaseHook() { override fun init() { if (!IS_TABLET) return loadClass("com.miui.contentextension.setting.activity.MainSettingsActivity").methodFinder() .first { name == "getFragment" }.createHook { setStaticObject( loadClass("miui.os.Build"), "IS_TABLET", false ) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/contentextension/UseThirdPartyBrowser.java ================================================ package com.sevtinge.cemiuiler.module.hook.contentextension; import android.app.SearchManager; import android.content.Context; import android.content.Intent; import android.net.Uri; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class UseThirdPartyBrowser extends BaseHook { @Override public void init() { // XposedBridge.log("Hook到传送门进程!"); final Class clazz = XposedHelpers.findClass("com.miui.contentextension.utils.AppsUtils", lpparam.classLoader); // getClassInfo(clazz); XposedHelpers.findAndHookMethod(clazz, "getIntentWithBrowser", String.class, new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable { XposedLogUtils.logI("com.miui.contentextension hooked url " + param.args[0].toString()); Uri uri = Uri.parse(param.args[0].toString()); Intent intent = new Intent(); intent.setAction("android.intent.action.VIEW"); intent.setData(uri); return intent; } }); XposedHelpers.findAndHookMethod(clazz, "openGlobalSearch", Context.class, String.class, String.class, new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { XposedLogUtils.logI("com.miui.contentextension hooked all-search on, word is " + param.args[1].toString() + ", from " + param.args[2].toString()); try { Intent intent = new Intent(); intent.setAction(Intent.ACTION_WEB_SEARCH); intent.putExtra(SearchManager.QUERY, param.args[1].toString()); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ((Context) param.args[0]).startActivity(intent); } catch (Exception e) { XposedLogUtils.logE(TAG, e); } return null; } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/creation/UnlockCreation.kt ================================================ package com.sevtinge.cemiuiler.module.hook.creation import com.github.kyuubiran.ezxhelper.ClassUtils.setStaticObject import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.LazyClass.clazzMiuiBuild object UnlockCreation : BaseHook() { override fun init() { setStaticObject(clazzMiuiBuild, "IS_TABLET", true) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/downloads/FuckXlDownload.java ================================================ package com.sevtinge.cemiuiler.module.hook.downloads; import android.os.Environment; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.io.File; import java.io.FileNotFoundException; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; public class FuckXlDownload extends BaseHook { private static final String TARGET_PACKAGE = "com.android.providers.downloads"; private static final File TARGET_PATH = new File(Environment.getExternalStorageDirectory(), ".xlDownload").getAbsoluteFile(); @Override public void init() { if (!TARGET_PACKAGE.equals(lpparam.packageName)) return; XposedLogUtils.logI("Target path = " + TARGET_PATH); XposedHelpers.findAndHookMethod(File.class, "mkdirs", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { final boolean isXlDownload = ((File) param.thisObject).getAbsoluteFile().equals(TARGET_PATH); if (isXlDownload) { XposedLogUtils.logI("blocked"); param.setThrowable(new FileNotFoundException("blocked")); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/externalstorage/DisableFolderCantUse.java ================================================ package com.sevtinge.cemiuiler.module.hook.externalstorage; import com.sevtinge.cemiuiler.module.base.BaseHook; public class DisableFolderCantUse extends BaseHook { @Override public void init() { findAndHookMethod("com.android.externalstorage.ExternalStorageProvider", "shouldBlockFromTree", String.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(false); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/fileexplorer/SelectName.kt ================================================ package com.sevtinge.cemiuiler.module.hook.fileexplorer import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.getObjectField object SelectName : BaseHook() { override fun init() { loadClass("com.android.fileexplorer.view.FileListItem").methodFinder().first { name == "onFinishInflate" }.createHook { after { (it.thisObject.getObjectField("mFileNameTextView") as TextView).apply { setTextIsSelectable(mPrefsMap.getBoolean("file_explorer_can_selectable")) isSingleLine = mPrefsMap.getBoolean("file_explorer_is_single_line") } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableHdrEnhance.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableHdrEnhance extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.gallery.domain.DeviceFeature", "isSupportHDREnhance", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableIdPhoto.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableIdPhoto extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.mediaeditor.api.MediaEditorApiHelper", "isIDPhotoAvailable", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.miui.gallery.domain.IDPhotoEntranceUtils", "isDeviceSupportIDPhoto", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.miui.gallery.domain.IDPhotoEntranceUtils", "getIdType", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(2); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableMagicMatting.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableMagicMatting extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.mediaeditor.api.MediaEditorApiHelper", "isMagicMattingAvailable", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableMagicSky.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableMagicSky extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.gallery.util.FilterSkyEntranceUtils", "showSingleFilterSky", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableOcr.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableOcr extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.gallery.ui.photoPage.ocr.OCRHelper", "isSupportLocalOCR", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.miui.gallery.ui.photoPage.ocr.OCRHelper", "isSupportOCR", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableOcrForm.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableOcrForm extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.gallery.util.RecognizeFormUtil", "isAvailable", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnablePdf.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnablePdf extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.gallery.request.PicToPdfHelper", "isPicToPdfSupport", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnablePhotoMovie.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnablePhotoMovie extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.mediaeditor.api.MediaEditorApiHelper", "isPhotoMovieAvailable", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.miui.gallery.domain.DeviceFeature", "isDeviceSupportPhotoMovie", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableRemover2.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableRemover2 extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.gallery.editor.photo.app.remover2.sdk.Remover2CheckHelper", "isRemover2Support", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableTextYanhua.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableTextYanhua extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.gallery.domain.SkyCheckHelper", "isSupportTextYanhua", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableVideoEditor.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableVideoEditor extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.mediaeditor.api.MediaEditorApiHelper", "isVideoEditorAvailable", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.miui.mediaeditor.api.MediaEditorApiHelper", "isVlogAvailable", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/gallery/EnableVideoPost.java ================================================ package com.sevtinge.cemiuiler.module.hook.gallery; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class EnableVideoPost extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.mediaeditor.api.MediaEditorApiHelper", "isVideoPostAvailable", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/guardprovider/DisableUploadAppList.java ================================================ package com.sevtinge.cemiuiler.module.hook.guardprovider; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import org.json.JSONArray; import org.json.JSONObject; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; public class DisableUploadAppList extends BaseHook { @Override public void init(/*final XC_LoadPackage.LoadPackageParam lpparam*/) { if (lpparam.packageName.equals("com.miui.guardprovider")) { XposedLogUtils.logI("Start to hook package " + lpparam.packageName); // Debug mode flag process final Class guardApplication = XposedHelpers.findClass("com.miui.guardprovider.GuardApplication", lpparam.classLoader); if (guardApplication != null) { Field[] guardApplicationFields = guardApplication.getDeclaredFields(); for (Field field : guardApplicationFields) { if ("c".equals(field.getName())) { XposedHelpers.setStaticBooleanField(guardApplication, "c", true); XposedLogUtils.logI("Info: GuardProvider will work as debug mode!"); } XposedLogUtils.logI("Warning: GuardProvider debug mode flag not found!"); } } else { XposedLogUtils.logI("Warning: GuardApplication class not found. GuardProvider will not work as debug mode! "); } // Prevent miui from uploading app list final Class antiDefraudAppManager = XposedHelpers.findClassIfExists("com.miui.guardprovider.engine.mi.antidefraud.AntiDefraudAppManager", lpparam.classLoader); if (antiDefraudAppManager == null) { XposedLogUtils.logI("Skip: AntiDefraudAppManager class not found."); return; } else { XposedLogUtils.logI("Info: AntiDefraudAppManager class found."); } final Method[] methods = antiDefraudAppManager.getDeclaredMethods(); Method getAllUnSystemAppsStatus = null; for (Method method : methods) { if ("getAllUnSystemAppsStatus".equals(method.getName()) && method.getParameterTypes().length == 1) { getAllUnSystemAppsStatus = method; break; } } if (getAllUnSystemAppsStatus == null) { XposedLogUtils.logI("Skip: getAllUnSystemAppsStatus method not found."); return; } else { XposedLogUtils.logI("Info: getAllUnSystemAppsStatus method found."); } XposedBridge.hookMethod(getAllUnSystemAppsStatus, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam methodHookParam) throws Throwable { List list = (List) methodHookParam.args[0]; String MIUI_VERSION = null; Field[] antiDefraudAppManagerFields = antiDefraudAppManager.getDeclaredFields(); for (Field field : antiDefraudAppManagerFields) { if (field.getName().equals("MIUI_VERSION")) { MIUI_VERSION = (String) XposedHelpers.getStaticObjectField(antiDefraudAppManager, "MIUI_VERSION"); } } if (MIUI_VERSION == null) { XposedLogUtils.logI("Warning: Can't get MIUI_VERSION."); } String uuid = null; final Class uuidHelper = XposedHelpers.findClassIfExists("i.b", lpparam.classLoader); if (uuidHelper != null) { final Method[] uuidHelperMethods = uuidHelper.getDeclaredMethods(); Method getUUID = null; for (Method method : uuidHelperMethods) { if (method.getName().equals("b") && method.getParameterTypes().length == 0) { getUUID = method; break; } } if (getUUID != null) { getUUID.setAccessible(true); uuid = (String) getUUID.invoke(methodHookParam); } else { XposedLogUtils.logI("Warning: getUUID method not found."); } } else { XposedLogUtils.logI("Warning: uuidHelper class not found."); } JSONObject jSONObject = new JSONObject(); jSONObject.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000)); jSONObject.put("os", MIUI_VERSION); jSONObject.put("biz_id", "virus_scan"); jSONObject.put("uuid", uuid); JSONArray jSONArray = new JSONArray(); for (int i2 = 0; i2 < list.size(); i2++) { JSONObject jSONObject2 = new JSONObject(); String pkgName = null; String version = null; String sign = null; String appName = null; Object antiDefraudAppInfo = (Object) list.get(i2); Field[] fields = antiDefraudAppInfo.getClass().getDeclaredFields(); for (Field filed : fields) { filed.setAccessible(true); if (filed.getName().equals("pkgName")) { pkgName = (String) filed.get(antiDefraudAppInfo); } else if (filed.getName().equals("version")) { version = (String) filed.get(antiDefraudAppInfo); } else if (filed.getName().equals("sign")) { sign = (String) filed.get(antiDefraudAppInfo); } else if (filed.getName().equals("appName")) { appName = (String) filed.get(antiDefraudAppInfo); } } jSONObject2.put("pkg", pkgName); jSONObject2.put("version", version); jSONObject2.put("signature", sign); jSONObject2.put("appname", appName); jSONArray.put(jSONObject2); } jSONObject.put("content", jSONArray); XposedLogUtils.logI("Info: Intercept=" + jSONObject.toString()); methodHookParam.setResult(null); } }); } } /* @Override public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) { if (lpparam.packageName.equals("com.miui.guardprovider")) { XposedBridge.log("Cemiuiler: Start to hook package " + lpparam.packageName); // Debug mode flag process final Class guardApplication = XposedHelpers.findClass("com.miui.guardprovider.GuardApplication", lpparam.classLoader); if (guardApplication != null) { Field[] guardApplicationFields = guardApplication.getDeclaredFields(); for (Field field : guardApplicationFields) { if (field.getName().equals("c")) { XposedHelpers.setStaticBooleanField(guardApplication, "c", true); XposedBridge.log("Cemiuiler: Info: GuardProvider will work as debug mode!"); } XposedBridge.log("Cemiuiler: Warning: GuardProvider debug mode flag not found!"); } } else { XposedBridge.log("Cemiuiler: Warning: GuardApplication class not found. GuardProvider will not work as debug mode! "); } // Prevent miui from uploading app list final Class antiDefraudAppManager = XposedHelpers.findClassIfExists("com.miui.guardprovider.engine.mi.antidefraud.AntiDefraudAppManager", lpparam.classLoader); if (antiDefraudAppManager == null) { XposedBridge.log("Cemiuiler: Skip: AntiDefraudAppManager class not found."); return; } else { XposedBridge.log("Cemiuiler: Info: AntiDefraudAppManager class found."); } final Method[] methods = antiDefraudAppManager.getDeclaredMethods(); Method getAllUnSystemAppsStatus = null; for (Method method : methods) { if (method.getName().equals("getAllUnSystemAppsStatus") && method.getParameterTypes().length == 1) { getAllUnSystemAppsStatus = method; break; } } if (getAllUnSystemAppsStatus == null) { XposedBridge.log("Cemiuiler: Skip: getAllUnSystemAppsStatus method not found."); return; } else { XposedBridge.log("Cemiuiler: Info: getAllUnSystemAppsStatus method found."); } XposedBridge.hookMethod(getAllUnSystemAppsStatus, new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam methodHookParam) throws Throwable { List list = (List) methodHookParam.args[0]; String MIUI_VERSION = null; Field[] antiDefraudAppManagerFields = antiDefraudAppManager.getDeclaredFields(); for (Field field : antiDefraudAppManagerFields) { if (field.getName().equals("MIUI_VERSION")) { MIUI_VERSION = (String) XposedHelpers.getStaticObjectField(antiDefraudAppManager, "MIUI_VERSION"); } } if (MIUI_VERSION == null) { XposedBridge.log("Cemiuiler: Warning: Can't get MIUI_VERSION."); } String uuid = null; final Class uuidHelper = XposedHelpers.findClassIfExists("i.b", lpparam.classLoader); if (uuidHelper != null) { final Method[] uuidHelperMethods = uuidHelper.getDeclaredMethods(); Method getUUID = null; for (Method method : uuidHelperMethods) { if (method.getName().equals("b") && method.getParameterTypes().length == 0) { getUUID = method; break; } } if (getUUID != null) { getUUID.setAccessible(true); uuid = (String) getUUID.invoke(methodHookParam); } else { XposedBridge.log("Cemiuiler: Warning: getUUID method not found."); } } else { XposedBridge.log("Cemiuiler: Warning: uuidHelper class not found."); } JSONObject jSONObject = new JSONObject(); jSONObject.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000)); jSONObject.put("os", MIUI_VERSION); jSONObject.put("biz_id", "virus_scan"); jSONObject.put("uuid", uuid); JSONArray jSONArray = new JSONArray(); for (int i2 = 0; i2 < list.size(); i2++) { JSONObject jSONObject2 = new JSONObject(); String pkgName = null; String version = null; String sign = null; String appName = null; Object antiDefraudAppInfo = (Object) list.get(i2); Field[] fields = antiDefraudAppInfo.getClass().getDeclaredFields(); for (Field filed : fields) { filed.setAccessible(true); if (filed.getName().equals("pkgName")) { pkgName = (String) filed.get(antiDefraudAppInfo); } else if (filed.getName().equals("version")) { version = (String) filed.get(antiDefraudAppInfo); } else if (filed.getName().equals("sign")) { sign = (String) filed.get(antiDefraudAppInfo); } else if (filed.getName().equals("appName")) { appName = (String) filed.get(antiDefraudAppInfo); } } jSONObject2.put("pkg", pkgName); jSONObject2.put("version", version); jSONObject2.put("signature", sign); jSONObject2.put("appname", appName); jSONArray.put(jSONObject2); } jSONObject.put("content", jSONArray); XposedBridge.log("Cemiuiler: Info: Intercept=" + jSONObject.toString()); methodHookParam.setResult(null); } }); } }*/ } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/guardprovider/DisableUploadAppListNew.kt ================================================ package com.sevtinge.cemiuiler.module.hook.guardprovider import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.replaceMethod object DisableUploadAppListNew : BaseHook() { @Throws(NoSuchMethodException::class) override fun init() { /*val antiDefraudAppManager = mGuardProviderResultMethodsMap["AntiDefraudAppManager"]!! assert(antiDefraudAppManager.size == 1) val antiDefraudAppManagerDescriptor = antiDefraudAppManager.first() val antiDefraudAppManagerMethod: Method = antiDefraudAppManagerDescriptor.getMethodInstance(lpparam.classLoader) antiDefraudAppManagerMethod.replaceMethod { return@replaceMethod null }*/ dexKitBridge.findMethod { matcher { addUsingStringsEquals("AntiDefraudAppManager", "https://flash.sec.miui.com/detect/app") } }.forEach { it.getMethodInstance(lpparam.classLoader).replaceMethod { return@replaceMethod null } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/AllAppsBlur.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import android.app.Activity; import com.sevtinge.cemiuiler.module.base.BaseHook; public class AllAppsBlur extends BaseHook { Class mLauncher; Class mBlurUtils; Class mAllAppsTransitionController; Class mActivityCls; Activity mActivity; @Override public void init() { mActivityCls = Activity.class; mLauncher = findClassIfExists("com.miui.home.launcher.Launcher"); mBlurUtils = findClassIfExists("com.miui.home.launcher.common.BlurUtils"); mAllAppsTransitionController = findClassIfExists("com.miui.home.launcher.allapps.BaseAllAppsContainerView"); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/AnimDurationRatio.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object AnimDurationRatio : BaseHook() { override fun init() { val value1 = mPrefsMap.getInt("home_title_animation_speed", 100).toFloat() / 100f val value2 = mPrefsMap.getInt("home_recent_animation_speed", 100).toFloat() / 100f loadClass("com.miui.home.recents.util.RectFSpringAnim").methodFinder().first { name == "getModifyResponse" }.createHook { before { it.result = it.args[0] as Float * value1 } } loadClass("com.miui.home.launcher.common.DeviceLevelUtils").methodFinder().first { name == "getDeviceLevelTransitionAnimRatio" }.createHook { before { it.result = value2 } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/FreeFormCountForHome.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class FreeFormCountForHome extends BaseHook { Class mRecentsAndFSGesture; @Override public void init() { mRecentsAndFSGesture = findClassIfExists("com.miui.home.launcher.RecentsAndFSGestureUtils"); hookAllMethods(mRecentsAndFSGesture, "canTaskEnterMiniSmallWindow", XC_MethodReplacement.returnConstant(true)); hookAllMethods(mRecentsAndFSGesture, "canTaskEnterSmallWindow", XC_MethodReplacement.returnConstant(true)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/HideNavigationBar.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import android.provider.Settings; import android.view.MotionEvent; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class HideNavigationBar extends BaseHook { @Override public void init() { /*横屏隐藏*/ findAndHookMethod("com.miui.home.recents.views.RecentsContainer", "showLandscapeOverviewGestureView", boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.args[0] = false; } } ); /*锁定返回*/ findAndHookMethod("com.miui.home.recents.NavStubView", "isMistakeTouch", new MethodHook() { @Override protected void before(MethodHookParam param) { View navView = (View) param.thisObject; boolean misTouch = false; boolean setting = Settings.Global.getInt(navView.getContext().getContentResolver(), "show_mistake_touch_toast", 1) != 0; if (setting) { boolean mIsShowStatusBar = XposedHelpers.getBooleanField(param.thisObject, "mIsShowStatusBar"); if (!mIsShowStatusBar) { misTouch = (boolean) XposedHelpers.callMethod(param.thisObject, "isLandScapeActually"); } } param.setResult(misTouch); } } ); /*横屏设置状态*/ findAndHookMethod("com.miui.home.recents.NavStubView", "onPointerEvent", MotionEvent.class, new MethodHook() { @Override protected void before(MethodHookParam param) { boolean mIsInFsMode = XposedHelpers.getBooleanField(param.thisObject, "mIsInFsMode"); if (!mIsInFsMode) { MotionEvent motionEvent = (MotionEvent) param.args[0]; if (motionEvent.getAction() == 0) { XposedHelpers.setObjectField(param.thisObject, "mHideGestureLine", true); } } } } ); /*恢复状态*/ findAndHookMethod("com.miui.home.recents.NavStubView", "updateScreenSize", new MethodHook() { @Override protected void before(MethodHookParam param) { XposedHelpers.setObjectField(param.thisObject, "mHideGestureLine", false); } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/HomePortraitReverse.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import android.app.Activity; import android.content.pm.ActivityInfo; import android.os.Bundle; import com.sevtinge.cemiuiler.module.base.BaseHook; public class HomePortraitReverse extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.launcher.Launcher", "onCreate", Bundle.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Activity act = (Activity) param.thisObject; act.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/MaxFreeForm.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home import android.util.ArraySet import com.github.kyuubiran.ezxhelper.ClassUtils import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.ObjectHelper.Companion.objectHelper import com.github.kyuubiran.ezxhelper.ObjectUtils import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class MaxFreeForm : BaseHook() { override fun init() { // CanTaskEnterSmallWindow val clazzRecentsAndFSGestureUtils = loadClass("com.miui.home.launcher.RecentsAndFSGestureUtils") clazzRecentsAndFSGestureUtils.methodFinder().filter { name == "canTaskEnterSmallWindow" }.toList().createHooks { returnConstant(true) } // CanTaskEnterMiniSmallWindow clazzRecentsAndFSGestureUtils.methodFinder().filter { name == "canTaskEnterMiniSmallWindow" }.toList().createHooks { before { it.result = ClassUtils.invokeStaticMethodBestMatch( loadClass("com.miui.home.smallwindow.SmallWindowStateHelper"), "getInstance" )!!.objectHelper() .invokeMethodBestMatch("canEnterMiniSmallWindow") as Boolean } } // StartSmallWindow loadClass("com.miui.home.smallwindow.SmallWindowStateHelperUseManager").methodFinder() .filterByName("canEnterMiniSmallWindow").first().createHook { before { it.result = ObjectUtils.getObjectOrNullAs>( it.thisObject, "mMiniSmallWindowInfoSet" )!!.isEmpty() } } loadClass("miui.app.MiuiFreeFormManager").methodFinder() .filterByName("getAllFreeFormStackInfosOnDisplay") .toList().createHooks { before { param -> if (Throwable().stackTrace.any { it.className == "android.util.MiuiMultiWindowUtils" && it.methodName == "startSmallFreeform" }) { param.result = null } } } loadClass("android.util.MiuiMultiWindowUtils").methodFinder() .filterByName("hasSmallFreeform").toList().createHooks { before { param -> if (Throwable().stackTrace.any { it.className == "android.util.MiuiMultiWindowUtils" && it.methodName == "startSmallFreeform" }) { param.result = false } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/ScreenSwipe.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import android.app.Activity; import android.content.Context; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import com.sevtinge.cemiuiler.module.app.GlobalActions; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.PrefsUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedHelpers; public class ScreenSwipe extends BaseHook { Class mLauncher; Class mWorkspace; @Override public void init() { mLauncher = findClassIfExists("com.miui.home.launcher.Launcher"); mWorkspace = findClassIfExists("com.miui.home.launcher.Workspace"); findAndHookMethod(mWorkspace, "onVerticalGesture", int.class, MotionEvent.class, new MethodHook() { @Override protected void before(MethodHookParam param) { if ((boolean) XposedHelpers.callMethod(param.thisObject, "isInNormalEditingMode")) return; String key = null; Context helperContext = ((ViewGroup) param.thisObject).getContext(); int numOfFingers = 1; if (param.args[1] != null) numOfFingers = ((MotionEvent) param.args[1]).getPointerCount(); if ((int) param.args[0] == 11) { if (numOfFingers == 1) key = "prefs_key_home_gesture_down_swipe"; else if (numOfFingers == 2) key = "prefs_key_home_gesture_down_swipe2"; if (GlobalActions.handleAction(helperContext, key)) param.setResult(true); } else if ((int) param.args[0] == 10) { if (numOfFingers == 1) key = "prefs_key_home_gesture_up_swipe"; else if (numOfFingers == 2) key = "prefs_key_home_gesture_up_swipe2"; if (GlobalActions.handleAction(helperContext, key)) param.setResult(true); } } }); findAndHookMethod(mLauncher, "onCreate", Bundle.class, new MethodHook() { @Override protected void after(final MethodHookParam param) { final Activity act = (Activity) param.thisObject; Handler mHandler = (Handler) XposedHelpers.getObjectField(act, "mHandler"); new PrefsUtils.SharedPrefsObserver(act, mHandler) { @Override public void onChange(Uri uri) { try { String type = uri.getPathSegments().get(1); String key = uri.getPathSegments().get(2); if (key.contains("prefs_key_home_gesture_down_swipe")) switch (type) { case "string" -> mPrefsMap.put(key, PrefsUtils.getSharedStringPrefs(act, key, "")); case "integer" -> mPrefsMap.put(key, PrefsUtils.getSharedIntPrefs(act, key, 1)); case "boolean" -> mPrefsMap.put(key, PrefsUtils.getSharedBoolPrefs(act, key, false)); } } catch (Throwable t) { LogD(TAG, "setAction", t); } } }; } }); findAndHookMethodSilently("com.miui.home.launcher.uioverrides.StatusBarSwipeController", "canInterceptTouch", MotionEvent.class, new MethodHook() { @Override protected void before(final MethodHookParam param) { if (mPrefsMap.getInt("home_gesture_down_swipe_action", 0) > 0) param.setResult(false); } }); // content_center, global_search, notification_bar findAndHookMethodSilently("com.miui.home.launcher.allapps.LauncherMode", "getPullDownGesture", Context.class, new MethodHook() { @Override protected void after(final MethodHookParam param) { if (PrefsUtils.getSharedIntPrefs((Context) param.args[0], "prefs_key_home_gesture_down_swipe_action", 1) > 1) param.setResult("no_action"); } }); // content_center, global_search findAndHookMethodSilently("com.miui.home.launcher.allapps.LauncherMode", "getSlideUpGesture", Context.class, new MethodHook() { @Override protected void before(final MethodHookParam param) { if (PrefsUtils.getSharedIntPrefs((Context) param.args[0], "prefs_key_home_gesture_up_swipe_action", 0) > 0) param.setResult("no_action"); } }); if (findAndHookMethodSilently("com.miui.home.launcher.DeviceConfig", "isGlobalSearchEnable", Context.class, new MethodHook() { @Override protected void before(final MethodHookParam param) { if (PrefsUtils.getSharedIntPrefs((Context) param.args[0], "prefs_key_home_gesture_up_swipe_action", 0) > 0) param.setResult(false); } })) { findAndHookMethodSilently("com.miui.home.launcher.search.SearchEdgeLayout", "isTopSearchEnable", new MethodHook() { @Override protected void before(final MethodHookParam param) { View view = (View) param.thisObject; if (PrefsUtils.getSharedIntPrefs(view.getContext(), "prefs_key_home_gesture_down_swipe_action", 0) > 0) param.setResult(false); } }); findAndHookMethodSilently("com.miui.home.launcher.search.SearchEdgeLayout", "isBottomGlobalSearchEnable", new MethodHook() { @Override protected void before(final MethodHookParam param) { View view = (View) param.thisObject; if (PrefsUtils.getSharedIntPrefs(view.getContext(), "prefs_key_home_gesture_up_swipe_action", 0) > 0) param.setResult(false); } }); findAndHookMethodSilently("com.miui.home.launcher.DeviceConfig", "isGlobalSearchBottomEffectEnable", Context.class, new MethodHook() { @Override protected void before(final MethodHookParam param) { if (PrefsUtils.getSharedIntPrefs((Context) param.args[0], "prefs_key_home_gesture_up_swipe_action", 0) > 0) param.setResult(false); } }); } else if (!findAndHookMethodSilently("com.miui.home.launcher.DeviceConfig", "allowedSlidingUpToStartGolbalSearch", Context.class, new MethodHook() { @Override protected void before(final MethodHookParam param) { if (PrefsUtils.getSharedIntPrefs((Context) param.args[0], "prefs_key_home_gesture_up_swipe_action", 0) > 0) param.setResult(false); } })) if (lpparam.packageName.equals("com.miui.home")) XposedLogUtils.logI(TAG, "Cannot disable swipe up search"); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/SeekPoints.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import android.content.Context; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.ViewGroup; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedHelpers; public class SeekPoints extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.launcher.ScreenView", "updateSeekPoints", int.class, new MethodHook() { @Override protected void before(final MethodHookParam param) throws Throwable { showSeekBar((View) param.thisObject); } }); findAndHookMethod("com.miui.home.launcher.ScreenView", "addView", View.class, int.class, ViewGroup.LayoutParams.class, new MethodHook() { @Override protected void before(final MethodHookParam param) throws Throwable { showSeekBar((View) param.thisObject); } }); findAndHookMethod("com.miui.home.launcher.ScreenView", "removeScreen", int.class, new MethodHook() { @Override protected void before(final MethodHookParam param) throws Throwable { showSeekBar((View) param.thisObject); } }); findAndHookMethod("com.miui.home.launcher.ScreenView", "removeScreensInLayout", int.class, int.class, new MethodHook() { @Override protected void before(final MethodHookParam param) throws Throwable { showSeekBar((View) param.thisObject); } }); } private void showSeekBar(View workspace) { if (!"Workspace".equals(workspace.getClass().getSimpleName())) return; boolean isInEditingMode = (boolean) XposedHelpers.callMethod(workspace, "isInNormalEditingMode"); View mScreenSeekBar = (View) XposedHelpers.getObjectField(workspace, "mScreenSeekBar"); if (mScreenSeekBar == null) { XposedLogUtils.logI("showSeekBar", "HideSeekPointsHook Cannot find seekbar"); return; } Context mContext = workspace.getContext(); Handler mHandler = (Handler) XposedHelpers.getAdditionalInstanceField(workspace, "mHandlerEx"); if (mHandler == null) { mHandler = new Handler(mContext.getMainLooper()) { @Override public void handleMessage(Message msg) { View seekBar = (View) msg.obj; if (seekBar != null) seekBar.animate().alpha(0.0f).setDuration(600).withEndAction(new Runnable() { @Override public void run() { seekBar.setVisibility(View.GONE); } }); } }; XposedHelpers.setAdditionalInstanceField(workspace, "mHandlerEx", mHandler); } if (mHandler == null) { XposedLogUtils.logI("showSeekBar", "HideSeekPointsHook Cannot create handler"); return; } if (mHandler.hasMessages(666)) mHandler.removeMessages(666); mScreenSeekBar.animate().cancel(); if (!isInEditingMode && XposedInit.mPrefsMap.getStringAsInt("home_other_seek_points", 0) == 2) { mScreenSeekBar.setAlpha(0.0f); mScreenSeekBar.setVisibility(View.GONE); return; } mScreenSeekBar.setVisibility(View.VISIBLE); mScreenSeekBar.animate().alpha(1.0f).setDuration(300); if (!isInEditingMode) { Message msg = Message.obtain(mHandler, 666); msg.obj = mScreenSeekBar; mHandler.sendMessageDelayed(msg, 1500); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/SetDeviceLevel.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.hookBeforeMethod import com.sevtinge.cemiuiler.utils.replaceMethod object SetDeviceLevel : BaseHook() { override fun init() { val mDeviceLevelUtilsClass = loadClass("com.miui.home.launcher.common.DeviceLevelUtils") val mSystemPropertiesClass = loadClass("android.os.SystemProperties") val mDeviceConfigClass = loadClass("com.miui.home.launcher.DeviceConfig") try { loadClass("com.miui.home.launcher.common.CpuLevelUtils").methodFinder().first { name == "getQualcommCpuLevel" && parameterCount == 1 } } catch (e: Exception) { loadClass("miuix.animation.utils.DeviceUtils").methodFinder().first { name == "getQualcommCpuLevel" && parameterCount == 1 } }.createHook { returnConstant(2) } runCatching { mDeviceConfigClass.methodFinder().first { name == "isUseSimpleAnim" }.createHook { before { it.result = false } } } runCatching { mDeviceLevelUtilsClass.methodFinder().first { name == "getDeviceLevel" }.createHook { before { it.result = 2 } } } runCatching { mDeviceConfigClass.methodFinder().first { name == "isSupportCompleteAnimation" }.createHook { before { it.result = true } } } runCatching { mDeviceLevelUtilsClass.methodFinder().first { name == "isLowLevelOrLiteDevice" }.createHook { before { it.result = false } } } runCatching { mDeviceConfigClass.methodFinder().first { name == "isMiuiLiteVersion" }.createHook { before { it.result = false } } } runCatching { "com.miui.home.launcher.util.noword.NoWordSettingHelperKt".hookBeforeMethod( "isNoWordAvailable" ) { it.result = true } } runCatching { mSystemPropertiesClass.methodFinder().filter { name == "getBoolean" && parameterTypes[0] == String::class.java && parameterTypes[1] == Boolean::class.java }.toList().createHooks { before { if (it.args[0] == "ro.config.low_ram.threshold_gb") it.result = false if (it.args[0] == "ro.miui.backdrop_sampling_enabled") it.result = true } } } runCatching { "com.miui.home.launcher.common.Utilities".hookBeforeMethod( "canLockTaskView" ) { it.result = true } } runCatching { "com.miui.home.launcher.MIUIWidgetUtil".hookBeforeMethod( "isMIUIWidgetSupport" ) { it.result = true } } runCatching { "com.miui.home.launcher.MiuiHomeLog".findClass().replaceMethod( "log", String::class.java, String::class.java ) { return@replaceMethod null } } runCatching { "com.xiaomi.onetrack.OneTrack".hookBeforeMethod("isDisable") { it.result = true } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/StickyFloatingWindowsForHome.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedHelpers; public class StickyFloatingWindowsForHome extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.recents.views.RecentsContainer", "onAttachedToWindow", new MethodHook() { @SuppressLint("UnspecifiedRegisterReceiverFlag") @Override protected void after(MethodHookParam param) { Context mContext = (Context) XposedHelpers.callMethod(param.thisObject, "getContext"); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try { String pkgName = intent.getStringExtra("package"); if (pkgName != null) { XposedHelpers.callMethod(param.thisObject, "dismissRecentsToLaunchTargetTaskOrHome", pkgName, true); } } catch (Throwable t) { XposedLogUtils.logW(TAG, t); } } }, new IntentFilter(ACTION_PREFIX + "dismissRecentsWhenFreeWindowOpen")); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/ToastSlideAgain.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import android.view.MotionEvent; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; public class ToastSlideAgain extends BaseHook { public XC_MethodHook.Unhook unhook = null; @Override public void init() { findAndHookMethod("com.miui.home.recents.NavStubView", "onPointerEvent", MotionEvent.class, new MethodHook() { @Override protected void before(MethodHookParam param) { unhook = hookToast(); // XposedLogUtils.logI("im hook onPointerEvent"); } @Override protected void after(MethodHookParam param) { unHook(unhook); } } ); findAndHookMethod("com.miui.home.recents.GestureModeApp", "onStartGesture", new MethodHook() { @Override protected void before(MethodHookParam param) { unhook = hookToast(); // XposedLogUtils.logI("im hook onStartGesture"); } @Override protected void after(MethodHookParam param) { unHook(unhook); } } ); } public XC_MethodHook.Unhook hookToast() { return XposedHelpers.findAndHookMethod(findClassIfExists("android.widget.Toast"), "show", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { param.setResult(null); // XposedLogUtils.logI("im hook Toast show"); } } ); } public void unHook(XC_MethodHook.Unhook unhook) { if (unhook != null) { unhook.unhook(); // XposedLogUtils.logI("the unhook is: " + unhook); } // logE("the unhook is: null"); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/UnlockHotseatIcon.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.hookBeforeMethod class UnlockHotseatIcon : BaseHook() { override fun init() { "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("getHotseatMaxCount") { it.result = 99 } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/UserPresentAnimation.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UserPresentAnimation extends BaseHook { Class mUserPresentAnimationCompatV12Phone; @Override public void init() { mUserPresentAnimationCompatV12Phone = !isPad() ? findClassIfExists("com.miui.home.launcher.compat.UserPresentAnimationCompatV12Phone") : findClassIfExists("com.miui.home.launcher.compat.UserPresentAnimationCompatV12Spring"); findAndHookMethod(mUserPresentAnimationCompatV12Phone, "getSpringAnimator", View.class, int.class, float.class, float.class, float.class, float.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.args[4] = 0.5f; param.args[5] = 0.5f; } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/WidgetCornerRadius.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DisplayUtils; public class WidgetCornerRadius extends BaseHook { Context mContext; @Override public void init() { hookAllConstructors("com.miui.home.launcher.maml.MaMlHostView", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { mContext = (Context) param.args[0]; } }); hookAllMethods("com.miui.home.launcher.maml.MaMlHostView", "computeRoundedCornerRadius", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult((float) DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_widget_corner_radius", 0))); } }); hookAllConstructors("com.miui.home.launcher.LauncherAppWidgetHostView", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { mContext = (Context) param.args[0]; } }); hookAllMethods("com.miui.home.launcher.LauncherAppWidgetHostView", "computeRoundedCornerRadius", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult((float) DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_widget_corner_radius", 0))); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/WidgetCrack.java ================================================ package com.sevtinge.cemiuiler.module.hook.home; import com.sevtinge.cemiuiler.module.base.BaseHook; public class WidgetCrack extends BaseHook { @Override public void init() { hookAllMethods("com.miui.maml.widget.edit.MamlutilKt", "themeManagerSupportPaidWidget", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { param.setResult(false); } }); findAndHookMethod("com.miui.home.launcher.gadget.MaMlPendingHostView", "isCanAutoStartDownload", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/dock/DisableRecentsIcon.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.dock import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object DisableRecentsIcon : BaseHook() { override fun init() { loadClass("com.miui.home.launcher.hotseats.HotSeatsListRecentsAppProvider").methodFinder().first { name == "updateFinalRecommendTasks" }.createHook { before { param -> param.result = true } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/dock/DockCustom.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.dock; import android.app.Activity; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import com.sevtinge.cemiuiler.utils.DisplayUtils; import de.robv.android.xposed.XposedHelpers; public class DockCustom extends BaseHook { FrameLayout mDockView; boolean isFolderShowing; boolean isShowEditPanel; boolean isRecentShowing; Class mLauncherCls; Class mLauncherStateCls; Class mDeviceConfigCls; Class mFolderInfo; Class mBlurUtils; @Override public void init() { mLauncherCls = findClassIfExists("com.miui.home.launcher.Launcher"); mLauncherStateCls = findClassIfExists("com.miui.home.launcher.LauncherState"); mDeviceConfigCls = findClassIfExists("com.miui.home.launcher.DeviceConfig"); mFolderInfo = findClassIfExists("com.miui.home.launcher.FolderInfo"); mBlurUtils = findClassIfExists("com.miui.home.launcher.common.BlurUtils"); findAndHookMethod(mLauncherCls, "onCreate", Bundle.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Activity mActivity = (Activity) param.thisObject; FrameLayout mSearchBarContainer = (FrameLayout) XposedHelpers.callMethod(param.thisObject, "getSearchBarContainer"); FrameLayout mSearchEdgeLayout = (FrameLayout) mSearchBarContainer.getParent(); int mDockHeight = DisplayUtils.dip2px(mSearchBarContainer.getContext(), XposedInit.mPrefsMap.getInt("home_dock_bg_height", 80)); int mDockMargin = DisplayUtils.dip2px(mSearchBarContainer.getContext(), XposedInit.mPrefsMap.getInt("home_dock_bg_margin_horizontal", 30)); int mDockBottomMargin = DisplayUtils.dip2px(mSearchBarContainer.getContext(), XposedInit.mPrefsMap.getInt("home_dock_bg_margin_bottom", 30)); mDockView = new FrameLayout(mSearchBarContainer.getContext()); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mDockHeight); layoutParams.gravity = Gravity.BOTTOM; layoutParams.setMargins(mDockMargin, 0, mDockMargin, mDockBottomMargin); mDockView.setLayoutParams(layoutParams); mSearchEdgeLayout.addView(mDockView, 0); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { new BlurUtils(mDockView, "home_dock_bg_custom"); } findAndHookMethod(mLauncherCls, "isFolderShowing", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { isFolderShowing = (boolean) param.getResult(); } }); findAndHookMethod(mLauncherCls, "showEditPanel", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { isShowEditPanel = (boolean) param.args[0]; mDockView.setVisibility(isShowEditPanel ? View.GONE : View.VISIBLE); } }); findAndHookMethod(mLauncherCls, "openFolder", mFolderInfo, View.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { mDockView.setVisibility(View.GONE); } }); findAndHookMethod(mLauncherCls, "closeFolder", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { if (!isShowEditPanel) mDockView.setVisibility(View.VISIBLE); } }); findAndHookMethod(mBlurUtils, "fastBlurWhenEnterRecents", mLauncherCls, mLauncherStateCls, boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { mDockView.setVisibility(View.GONE); } }); } }); findAndHookMethod(mLauncherCls, "onStateSetStart", mLauncherStateCls, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { if (param.args[0].getClass().getSimpleName().equals("LauncherState") && !isFolderShowing && !isShowEditPanel) { mDockView.setVisibility(View.VISIBLE); } else { mDockView.setVisibility(View.GONE); } } }); /*findAndHookMethod(mDeviceConfigCls,"calcHotSeatsMarginTop", Context.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Context context = (Context) param.args[0]; param.setResult(DisplayUtils.dip2px(context, XposedInit.mPrefsMap.getInt("home_dock_margin_top",25))); } }); findAndHookMethod(mDeviceConfigCls,"calcHotSeatsMarginBottom", Context.class, boolean.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Context context = (Context) param.args[0]; param.setResult(DisplayUtils.dip2px(context, XposedInit.mPrefsMap.getInt("home_dock_icon_margin_bottom",90))); } });*/ } public GradientDrawable getDockBackground(Context context) { GradientDrawable mDockBackground = new GradientDrawable(); mDockBackground.setShape(GradientDrawable.RECTANGLE); mDockBackground.setColor(Color.argb(60, 255, 255, 255)); mDockBackground.setCornerRadius(DisplayUtils.dip2px(context, 22)); return mDockBackground; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/dock/FoldDeviceDock.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.dock import android.content.Context import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.hookAfterMethod import com.sevtinge.cemiuiler.utils.hookBeforeMethod import de.robv.android.xposed.XC_MethodHook object FoldDeviceDock : BaseHook() { override fun init() { // if (!mPrefsMap.getBoolean("home_fold_dock")) return var hook1: XC_MethodHook.Unhook? = null var hook2: XC_MethodHook.Unhook? = null var hook3: XC_MethodHook.Unhook? = null val mHotSeatsClass = loadClass("com.miui.home.launcher.hotseats.HotSeats") mHotSeatsClass.methodFinder().first { name == "initContent" }.createHook { before { hook1 = "com.miui.home.launcher.DeviceConfig".hookBeforeMethod( "isFoldDevice" ) { hookParam -> hookParam.result = true } } after { hook1?.unhook() } } try { mHotSeatsClass.methodFinder().first { name == "updateContent" } } catch (e: Exception) { mHotSeatsClass.methodFinder().first { name == "updateContentView" } }.createHook { before { hook2 = "com.miui.home.launcher.Application".hookBeforeMethod( "isInFoldLargeScreen" ) { hookParam -> hookParam.result = true } } after { hook2?.unhook() } } mHotSeatsClass.methodFinder().first { name == "isNeedUpdateItemInfo" }.createHook { before { hook3 = "com.miui.home.launcher.Application".hookBeforeMethod( "isInFoldLargeScreen" ) { hookParam -> hookParam.result = true } } after { hook3?.unhook() } } "com.miui.home.launcher.DeviceConfig".hookAfterMethod( "getHotseatMaxCount" ) { it.result = mPrefsMap.getInt("home_fold_dock_hotseat", 3) } "com.miui.home.launcher.hotseats.HotSeatsListRecentsAppProvider".hookBeforeMethod( "getLimitCount" ) { it.result = mPrefsMap.getInt("home_fold_dock_run", 2) } "com.miui.home.launcher.allapps.LauncherMode".hookBeforeMethod( "isHomeSupportSearchBar", Context::class.java ) { it.result = false } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/dock/FoldDock.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.dock; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class FoldDock extends BaseHook { Class mHotSeatsList; Class mHotSeatsListRecentsAppProvider; Class mDeviceConfig; Class mApplication; @Override public void init() { mHotSeatsList = findClassIfExists("com.miui.home.launcher.hotseats.HotSeatsList"); mHotSeatsListRecentsAppProvider = findClassIfExists("com.miui.home.launcher.hotseats.HotSeatsListRecentsAppProvider"); mDeviceConfig = findClassIfExists("com.miui.home.launcher.DeviceConfig"); mApplication = findClassIfExists("com.miui.home.launcher.Application"); findAndHookMethod(mHotSeatsListRecentsAppProvider, "getLimitCount", XC_MethodReplacement.returnConstant(0)); findAndHookMethod(mDeviceConfig, "getHotseatMaxCount", XC_MethodReplacement.returnConstant(5)); findAndHookMethod("com.miui.home.launcher.hotseats.HotSeats", "initContent", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { findAndHookMethod(mDeviceConfig, "isFoldDevice", XC_MethodReplacement.returnConstant(true)); } @Override protected void after(MethodHookParam param) throws Throwable { findAndHookMethod(mDeviceConfig, "isFoldDevice", XC_MethodReplacement.returnConstant(false)); } }); findAndHookMethod("com.miui.home.launcher.hotseats.HotSeats", "updateContentView", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { findAndHookMethod(mApplication, "isInFoldLargeScreen", XC_MethodReplacement.returnConstant(true)); } @Override protected void after(MethodHookParam param) throws Throwable { findAndHookMethod(mApplication, "isInFoldLargeScreen", XC_MethodReplacement.returnConstant(false)); } }); findAndHookMethod("com.miui.home.launcher.allapps.LauncherMode", "isHomeSupportSearchBar", Context.class, XC_MethodReplacement.returnConstant(false)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/dock/HideSeekPoint.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.dock import android.view.View import android.view.ViewGroup import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod object HideSeekPoint : BaseHook() { override fun init() { // if (!mPrefsMap.getBoolean("home_hide_seek_point")) return "com.miui.home.launcher.ScreenView".hookAfterMethod( "updateSeekPoints", Int::class.javaPrimitiveType ) { showSeekBar(it.thisObject as View) } "com.miui.home.launcher.ScreenView".hookAfterMethod( "addView", View::class.java, Int::class.javaPrimitiveType, ViewGroup.LayoutParams::class.java ) { showSeekBar(it.thisObject as View) } "com.miui.home.launcher.ScreenView".hookAfterMethod( "removeScreen", Int::class.javaPrimitiveType ) { showSeekBar(it.thisObject as View) } "com.miui.home.launcher.ScreenView".hookAfterMethod( "removeScreensInLayout", Int::class.javaPrimitiveType, Int::class.javaPrimitiveType ) { showSeekBar(it.thisObject as View) } } private fun showSeekBar(view: View) { if ("Workspace" != view.javaClass.simpleName) return val mScreenSeekBar = view.getObjectField("mScreenSeekBar") as View val isInEditingMode = view.callMethod("isInNormalEditingMode") as Boolean if (!isInEditingMode) { mScreenSeekBar.animate().cancel() mScreenSeekBar.visibility = View.GONE } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/dock/ShowDockIconTitle.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.dock import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.hookBeforeMethod object ShowDockIconTitle : BaseHook() { override fun init() { "com.miui.home.launcher.DeviceConfig".hookBeforeMethod("isHotseatsAppTitleHided") { it.result = false } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/drawer/AllAppsContainerViewBlur.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.drawer import android.app.Application import android.content.Context import android.os.Build import android.view.View import android.widget.FrameLayout import android.widget.RelativeLayout import android.widget.ViewSwitcher import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.getCornerRadiusTop import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookBeforeMethod import com.zhenxiang.blur.BlurFrameLayout import com.zhenxiang.blur.model.CornersRadius object AllAppsContainerViewBlur : BaseHook() { override fun init() { Application::class.java.hookBeforeMethod("attach", Context::class.java) { EzXHelper.initHandleLoadPackage(lpparam) EzXHelper.setLogTag(TAG) EzXHelper.setToastTag(TAG) EzXHelper.initAppContext(it.args[0] as Context) loadClass("com.miui.home.launcher.allapps.BaseAllAppsContainerView").methodFinder().filter { name == "onFinishInflate" }.toList().createHooks { after { hookParam -> val mCategoryContainer = hookParam.thisObject.getObjectField("mCategoryContainer") as ViewSwitcher val appsView = mCategoryContainer.parent as RelativeLayout val blur = BlurFrameLayout(mCategoryContainer.context) val radius = getCornerRadiusTop().toFloat() if (Build.VERSION.SDK_INT >= 31) { blur.blurController.apply { cornerRadius = CornersRadius.custom(radius, radius, 0f, 0f) } } val view = View(mCategoryContainer.context) blur.addView(view) (view.layoutParams as FrameLayout.LayoutParams).apply { width = FrameLayout.LayoutParams.MATCH_PARENT height = FrameLayout.LayoutParams.MATCH_PARENT } appsView.addView(blur, 0) loadClass("com.miui.home.launcher.allapps.BaseAllAppsContainerView").methodFinder().filter { name == "onResume" }.toList().createHooks { after { blur.refreshDrawableState() } } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/drawer/AppDrawer.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.drawer import android.view.View import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.ClassUtils.loadClassOrNull import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethodAs import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.getObjectFieldAs import com.sevtinge.cemiuiler.utils.hookAfterMethod object AppDrawer : BaseHook() { override fun init() { if (mPrefsMap.getBoolean("home_drawer_all")) { try { loadClassOrNull("com.miui.home.launcher.allapps.category.BaseAllAppsCategoryListContainer")!! .methodFinder() .first { name == "buildSortCategoryList" } } catch (e: Exception) { loadClass("com.miui.home.launcher.allapps.category.AllAppsCategoryListContainer").methodFinder() .first { name == "buildSortCategoryList" } }.createHook { after { val list = it.result as ArrayList<*> if (list.size > 1) { list.removeAt(0) it.result = list } } } } if (mPrefsMap.getBoolean("home_drawer_editor")) { "com.miui.home.launcher.allapps.AllAppsGridAdapter".hookAfterMethod( "onBindViewHolder", "com.miui.home.launcher.allapps.AllAppsGridAdapter.ViewHolder".findClass(), Int::class.javaPrimitiveType ) { if (it.args[0].callMethodAs("getItemViewType") == 64) { it.args[0].getObjectFieldAs("itemView").visibility = View.INVISIBLE } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/drawer/PinyinArrangement.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.drawer; import android.app.Activity; import com.github.promeg.pinyinhelper.Pinyin; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.Locale; import de.robv.android.xposed.XposedHelpers; public class PinyinArrangement extends BaseHook { Locale locale; Activity activity; @Override public void init() { findAndHookMethod("com.miui.home.launcher.compat.AlphabeticIndexCompat", "computeSectionName", CharSequence.class, new MethodHook() { @Override protected void before(MethodHookParam param) { CharSequence charSequence = (CharSequence) param.args[0]; String bucketLabel; String trim = (String) XposedHelpers.callStaticMethod(findClass("com.miui.home.launcher.common.Utilities"), "trim", charSequence); if (charSequence.length() > 0 && Pinyin.isChinese(charSequence.charAt(0))) { bucketLabel = String.valueOf(Pinyin.toPinyin(charSequence.toString(), "").charAt(0)); } else { Object o = XposedHelpers.getObjectField(param.thisObject, "mBaseIndex"); bucketLabel = (String) XposedHelpers.callMethod(o, "getBucketLabel", XposedHelpers.callMethod(o, "getBucketIndex", trim)); } // logE("bucketLabel: " + bucketLabel + " trim1: " + trim); String trim2 = (String) XposedHelpers.callStaticMethod(findClass("com.miui.home.launcher.common.Utilities"), "trim", bucketLabel); // logE("trim2: " + trim2); if (!trim2.isEmpty() || trim.length() <= 0) { param.setResult(bucketLabel); return; } int codePointAt = trim.codePointAt(0); param.setResult(Character.isDigit(codePointAt) ? "…" : Character.isLetter(codePointAt) ? (String) XposedHelpers.getObjectField(param.thisObject, "mDefaultMiscLabel") : "∙"); } } ); hookAllMethods("com.miui.home.launcher.allapps.BaseAlphabeticalAppsList", "onAppsUpdated", new MethodHook() { @Override protected void before(MethodHookParam param) { activity = (Activity) XposedHelpers.getObjectField(param.thisObject, "mLauncher"); locale = activity.getResources().getConfiguration().locale; activity.getResources().getConfiguration().setLocale(Locale.SIMPLIFIED_CHINESE); } @Override protected void after(MethodHookParam param) { activity.getResources().getConfiguration().setLocale(locale); } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/BigFolderIcon.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder; import com.sevtinge.cemiuiler.module.base.BaseHook; public class BigFolderIcon extends BaseHook { Class mFolderIcon; @Override public void init() { mFolderIcon = findClassIfExists("com.miui.home.launcher.folder.FolderIcon2x2_4"); findAndHookMethod(mFolderIcon, "getPreviewCount", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(5); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/BigFolderIconBlur.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import android.content.Context; import android.os.Build; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import com.sevtinge.cemiuiler.utils.DisplayUtils; import java.lang.reflect.Method; import de.robv.android.xposed.XposedHelpers; public class BigFolderIconBlur extends BaseHook { boolean isShowEditPanel; Class mLauncher; Class mFolderInfo; Class mFolderIcon; Class mLauncherState; Class mDragView; Class mFolderIcon2x2; Class mFolderIcon2x2_4; Class mFolderIcon2x2_9; @Override public void init() { mLauncher = findClassIfExists("com.miui.home.launcher.Launcher"); mFolderInfo = findClassIfExists("com.miui.home.launcher.FolderInfo"); mFolderIcon = findClassIfExists("com.miui.home.launcher.FolderIcon"); mLauncherState = findClassIfExists("com.miui.home.launcher.LauncherState"); mDragView = findClassIfExists("com.miui.home.launcher.DragView"); mFolderIcon2x2 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon2x2"); if (isPad()) { mFolderIcon2x2_4 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon4x4_16"); mFolderIcon2x2_9 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon3x3_9"); } else { mFolderIcon2x2_4 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon2x2_4"); mFolderIcon2x2_9 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon2x2_9"); } hookAllConstructors(mFolderIcon, new MethodHook() { @Override protected void after(MethodHookParam param) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); Object mDockBlur = XposedHelpers.getAdditionalInstanceField(param.thisObject, "mDockBlur"); if (mDockBlur != null) return; mDockBlur = new FrameLayout(mContext); XposedHelpers.setAdditionalInstanceField(param.thisObject, "mDockBlur", mDockBlur); } }); MethodHook mBigFolderIconBlur = new MethodHook() { @Override protected void after(MethodHookParam param) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); int mFolderWidth = DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_big_folder_icon_bg_width", 145)); int mFolderHeight = DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_big_folder_icon_bg_height", 145)); ImageView mIconImageView = (ImageView) XposedHelpers.getObjectField(param.thisObject, "mIconImageView"); FrameLayout mIconContainer = (FrameLayout) mIconImageView.getParent(); FrameLayout mDockBlur = (FrameLayout) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mDockBlur"); FrameLayout view = new FrameLayout(mIconImageView.getContext()); mIconImageView.setVisibility(View.GONE); mDockBlur.addView(view); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { new BlurUtils(mDockBlur, "home_big_folder_icon_bg_custom"); } mIconContainer.addView(mDockBlur, 0); FrameLayout.LayoutParams lp1 = (FrameLayout.LayoutParams) mDockBlur.getLayoutParams(); lp1.gravity = Gravity.CENTER; if(isPad()){ lp1.width = mFolderWidth * 2; lp1.height = mFolderHeight *2; }else { lp1.width = mFolderWidth; lp1.height = mFolderHeight; } findAndHookMethod(mLauncher, "showEditPanel", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) { isShowEditPanel = (boolean) param.args[0]; if (isShowEditPanel) { mDockBlur.setVisibility(View.GONE); mIconImageView.setVisibility(View.VISIBLE); } else { mDockBlur.setVisibility(View.VISIBLE); mIconImageView.setVisibility(View.GONE); } } }); findAndHookMethod(mLauncher, "openFolder", mFolderInfo, View.class, new MethodHook() { @Override protected void after(MethodHookParam param) { mDockBlur.setVisibility(View.GONE); } }); findAndHookMethod(mLauncher, "closeFolder", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) { if (!isShowEditPanel) mDockBlur.setVisibility(View.VISIBLE); } }); findAndHookMethod(mLauncher, "onStateSetStart", mLauncherState, new MethodHook() { @Override protected void after(MethodHookParam param) { if (param.args[0].getClass().getSimpleName().equals("LauncherState")) { mDockBlur.setVisibility(View.VISIBLE); } else { mDockBlur.setVisibility(View.GONE); } } }); } }; Method FolderIcon2x2_4_OnFinishInflate = XposedHelpers.findMethodExactIfExists(mFolderIcon2x2_4, "onFinishInflate", Void.TYPE); Method FolderIcon2x2_9_OnFinishInflate = XposedHelpers.findMethodExactIfExists(mFolderIcon2x2_9, "onFinishInflate", Void.TYPE); if (FolderIcon2x2_4_OnFinishInflate != null && FolderIcon2x2_9_OnFinishInflate != null) { findAndHookMethod(mFolderIcon2x2_4, "onFinishInflate", mBigFolderIconBlur); findAndHookMethod(mFolderIcon2x2_9, "onFinishInflate", mBigFolderIconBlur); } else if (mFolderIcon2x2 != null) { findAndHookMethod(mFolderIcon2x2, "onFinishInflate", mBigFolderIconBlur); } hookAllConstructors(mDragView, new MethodHook() { @Override protected void after(MethodHookParam param) { View mDragView = (View) param.thisObject; mDragView.setLayerType(View.LAYER_TYPE_HARDWARE, null); Object mDragInfo = XposedHelpers.getObjectField(param.thisObject, "mDragInfo"); int itemType = (int) XposedHelpers.getObjectField(mDragInfo, "itemType"); Object mLauncher = XposedHelpers.getObjectField(param.thisObject, "mLauncher"); boolean isFolderShowing = (boolean) XposedHelpers.callMethod(mLauncher, "isFolderShowing"); if (!isFolderShowing && itemType == 21) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { new BlurUtils(mDragView, "home_big_folder_icon_bg_custom"); } } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/BigFolderIconBlur1x2.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import android.content.Context; import android.os.Build; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import com.sevtinge.cemiuiler.utils.DisplayUtils; import de.robv.android.xposed.XposedHelpers; public class BigFolderIconBlur1x2 extends BaseHook { Class mFolderIcon1x2; boolean isShowEditPanel; Class mLauncher; Class mFolderInfo; Class mFolderIcon; Class mLauncherState; Class mDragView; @Override public void init() { if (isPad()) { mFolderIcon1x2 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon2x2_4"); } else { mFolderIcon1x2 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon1x2"); } mLauncher = findClassIfExists("com.miui.home.launcher.Launcher"); mFolderInfo = findClassIfExists("com.miui.home.launcher.FolderInfo"); mFolderIcon = findClassIfExists("com.miui.home.launcher.FolderIcon"); mLauncherState = findClassIfExists("com.miui.home.launcher.LauncherState"); mDragView = findClassIfExists("com.miui.home.launcher.DragView"); MethodHook mBigFolderIconBlur = new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); int mFolderWidth = DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_big_folder_icon_bg_width_1x2", 62)); int mFolderHeight = DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_big_folder_icon_bg_height_1x2", 145)); ImageView mIconImageView = (ImageView) XposedHelpers.getObjectField(param.thisObject, "mIconImageView"); FrameLayout mIconContainer = (FrameLayout) mIconImageView.getParent(); FrameLayout mDockBlur = (FrameLayout) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mDockBlur"); FrameLayout view = new FrameLayout(mIconImageView.getContext()); mIconImageView.setVisibility(View.GONE); mDockBlur.addView(view); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { new BlurUtils(mDockBlur, "home_big_folder_icon_bg_1x2_custom"); } mIconContainer.addView(mDockBlur, 0); FrameLayout.LayoutParams lp1 = (FrameLayout.LayoutParams) mDockBlur.getLayoutParams(); lp1.gravity = Gravity.CENTER; lp1.height = mFolderHeight; lp1.width = mFolderWidth; findAndHookMethod(mLauncher, "showEditPanel", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { isShowEditPanel = (boolean) param.args[0]; if (isShowEditPanel) { mDockBlur.setVisibility(View.GONE); mIconImageView.setVisibility(View.VISIBLE); } else { mDockBlur.setVisibility(View.VISIBLE); mIconImageView.setVisibility(View.GONE); } } }); findAndHookMethod(mLauncher, "openFolder", mFolderInfo, View.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { mDockBlur.setVisibility(View.GONE); } }); findAndHookMethod(mLauncher, "closeFolder", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { if (!isShowEditPanel) mDockBlur.setVisibility(View.VISIBLE); } }); findAndHookMethod(mLauncher, "onStateSetStart", mLauncherState, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { if (param.args[0].getClass().getSimpleName().equals("LauncherState")) { mDockBlur.setVisibility(View.VISIBLE); } else { mDockBlur.setVisibility(View.GONE); } } }); } }; findAndHookMethod(mFolderIcon1x2, "onFinishInflate", mBigFolderIconBlur); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/BigFolderIconBlur2x1.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import android.content.Context; import android.os.Build; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import com.sevtinge.cemiuiler.utils.DisplayUtils; import de.robv.android.xposed.XposedHelpers; public class BigFolderIconBlur2x1 extends BaseHook { Class mFolderIcon2x1; boolean isShowEditPanel; Class mLauncher; Class mFolderInfo; Class mFolderIcon; Class mLauncherState; Class mDragView; @Override public void init() { if (isPad()) { mFolderIcon2x1 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon4x2_8"); } else { mFolderIcon2x1 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon2x1"); } mLauncher = findClassIfExists("com.miui.home.launcher.Launcher"); mFolderInfo = findClassIfExists("com.miui.home.launcher.FolderInfo"); mFolderIcon = findClassIfExists("com.miui.home.launcher.FolderIcon"); mLauncherState = findClassIfExists("com.miui.home.launcher.LauncherState"); mDragView = findClassIfExists("com.miui.home.launcher.DragView"); MethodHook mBigFolderIconBlur = new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); int mFolderWidth = DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_big_folder_icon_bg_width_2x1", 145)); int mFolderHeight = DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_big_folder_icon_bg_height_2x1", 62)); ImageView mIconImageView = (ImageView) XposedHelpers.getObjectField(param.thisObject, "mIconImageView"); FrameLayout mIconContainer = (FrameLayout) mIconImageView.getParent(); FrameLayout mDockBlur = (FrameLayout) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mDockBlur"); FrameLayout view = new FrameLayout(mIconImageView.getContext()); mIconImageView.setVisibility(View.GONE); mDockBlur.addView(view); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { new BlurUtils(mDockBlur, "home_big_folder_icon_bg_2x1_custom"); } mIconContainer.addView(mDockBlur, 0); FrameLayout.LayoutParams lp1 = (FrameLayout.LayoutParams) mDockBlur.getLayoutParams(); lp1.gravity = Gravity.CENTER; if (isPad()) { lp1.width = mFolderWidth * 2; lp1.height = mFolderHeight * 2; }else { lp1.width = mFolderWidth; lp1.height = mFolderHeight; } findAndHookMethod(mLauncher, "showEditPanel", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { isShowEditPanel = (boolean) param.args[0]; if (isShowEditPanel) { mDockBlur.setVisibility(View.GONE); mIconImageView.setVisibility(View.VISIBLE); } else { mDockBlur.setVisibility(View.VISIBLE); mIconImageView.setVisibility(View.GONE); } } }); findAndHookMethod(mLauncher, "openFolder", mFolderInfo, View.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { mDockBlur.setVisibility(View.GONE); } }); findAndHookMethod(mLauncher, "closeFolder", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { if (!isShowEditPanel) mDockBlur.setVisibility(View.VISIBLE); } }); findAndHookMethod(mLauncher, "onStateSetStart", mLauncherState, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { if (param.args[0].getClass().getSimpleName().equals("LauncherState")) { mDockBlur.setVisibility(View.VISIBLE); } else { mDockBlur.setVisibility(View.GONE); } } }); } }; findAndHookMethod(mFolderIcon2x1, "onFinishInflate", mBigFolderIconBlur); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/BigFolderItemMaxCount.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedHelpers; public class BigFolderItemMaxCount extends BaseHook { Class mFolderIcon2x2; Class mFolderIcon2x2_9; Class mFolderIcon2x2_4; Class mBaseFolderIconPreviewContainer2X2; int mRealPvChildCount; @Override public void init() { mFolderIcon2x2 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon2x2"); mFolderIcon2x2_9 = findClassIfExists("com.miui.home.launcher.folder.FolderIconPreviewContainer2X2_9"); mFolderIcon2x2_4 = findClassIfExists("com.miui.home.launcher.folder.FolderIconPreviewContainer2X2_4"); mBaseFolderIconPreviewContainer2X2 = findClassIfExists("com.miui.home.launcher.folder.BaseFolderIconPreviewContainer2X2"); findAndHookMethod(mFolderIcon2x2_9, "preSetup2x2", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { mRealPvChildCount = (int) XposedHelpers.callMethod(param.thisObject, "getMRealPvChildCount"); XposedLogUtils.logI(TAG, "getMRealPvChildCount1:" + mRealPvChildCount); if (mRealPvChildCount < 10) { XposedHelpers.callMethod(param.thisObject, "setMItemsMaxCount", 9); XposedHelpers.callMethod(param.thisObject, "setMLargeIconNum", 9); } else { XposedHelpers.callMethod(param.thisObject, "setMItemsMaxCount", 12); XposedHelpers.callMethod(param.thisObject, "setMLargeIconNum", 8); } } }); findAndHookMethod(mFolderIcon2x2_4, "preSetup2x2", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { mRealPvChildCount = (int) XposedHelpers.callMethod(param.thisObject, "getMRealPvChildCount"); XposedLogUtils.logI(TAG, "getMRealPvChildCount1:" + mRealPvChildCount); if (mRealPvChildCount < 5) { XposedHelpers.callMethod(param.thisObject, "setMItemsMaxCount", 4); XposedHelpers.callMethod(param.thisObject, "setMLargeIconNum", 4); } else { XposedHelpers.callMethod(param.thisObject, "setMItemsMaxCount", 7); XposedHelpers.callMethod(param.thisObject, "setMLargeIconNum", 3); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/FolderAnimation.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder import com.github.kyuubiran.ezxhelper.ClassUtils.loadClassOrNull import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.hookAfterMethod import com.sevtinge.cemiuiler.utils.hookBeforeMethod import de.robv.android.xposed.XC_MethodHook import kotlin.math.abs class FolderAnimation : BaseHook() { var mLauncher: Class<*>? = null private var value1: Float? = null private var value2: Float? = null private var value3: Float? = null private var value4: Float? = null override fun init() {//|x-200| 50-150 value1 = abs(mPrefsMap.getInt("home_folder_anim_1", 90).toFloat() - 200) / 100 value2 = mPrefsMap.getInt("home_folder_anim_2", 30).toFloat() / 100 value3 = abs(mPrefsMap.getInt("home_folder_anim_3", 99).toFloat() - 200) / 100 value4 = mPrefsMap.getInt("home_folder_anim_4", 24).toFloat() / 100 val mSpringAnimator = findClassIfExists("com.miui.home.launcher.animate.SpringAnimator") var hook1: XC_MethodHook.Unhook? = null var hook2: XC_MethodHook.Unhook? = null for (i in 47..60) { val launcherClass = findClassIfExists("com.miui.home.launcher.Launcher$$i") if (launcherClass != null) { for (field in launcherClass.declaredFields) { if (field.name == "val\$folderInfo") { val mLauncherClass = loadClassOrNull("com.miui.home.launcher.Launcher$$i") ?: continue for (child in mLauncherClass.declaredFields) { if (child.name != "val\$folderInfo") continue mLauncherClass.methodFinder().first { name == "run" }.createHook { before { hook1 = mSpringAnimator.methodFinder().first { name == "setDampingResponse" && parameterTypes[0] == Float::class.javaPrimitiveType && parameterTypes[1] == Float::class.javaPrimitiveType }.createHook { before { it.args[0] = value1 it.args[1] = value2 } } } after { hook1?.unhook() } } break } } } } } "com.miui.home.launcher.Launcher".hookBeforeMethod("closeFolder", Boolean::class.java) { if (it.args[0] == true) { hook2 = mSpringAnimator.hookBeforeMethod( "setDampingResponse", Float::class.javaPrimitiveType, Float::class.javaPrimitiveType ) { hookParam -> hookParam.args[0] = value3 hookParam.args[1] = value4 } } } "com.miui.home.launcher.Launcher".hookAfterMethod("closeFolder", Boolean::class.java) { hook2?.unhook() } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/FolderAutoClose.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder import android.view.View import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.getBooleanField import com.sevtinge.cemiuiler.utils.hookAfterMethod object FolderAutoClose : BaseHook() { override fun init() { "com.miui.home.launcher.Launcher".hookAfterMethod( "launch", "com.miui.home.launcher.ShortcutInfo", View::class.java ) { val mHasLaunchedAppFromFolder = it.thisObject.getBooleanField("mHasLaunchedAppFromFolder") if (mHasLaunchedAppFromFolder) it.thisObject.callMethod("closeFolder") } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/FolderBlur.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder import android.annotation.SuppressLint import android.app.Activity import android.view.MotionEvent import android.view.View import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.* import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object FolderBlur : BaseHook() { @SuppressLint("SuspiciousIndentation") override fun init() { // 修复文件夹背景模糊与始终模糊壁纸冲突 if (mPrefsMap.getBoolean("home_other_always_blur_launcher_wallpaper")) return val folderInfo = findClassIfExists("com.miui.home.launcher.FolderInfo") val launcherClass = findClassIfExists("com.miui.home.launcher.Launcher") val blurUtilsClass = findClassIfExists("com.miui.home.launcher.common.BlurUtils") val navStubViewClass = findClassIfExists("com.miui.home.recents.NavStubView") val cancelShortcutMenuReasonClass = findClassIfExists("com.miui.home.launcher.shortcuts.CancelShortcutMenuReason") val applicationClass = findClassIfExists("com.miui.home.launcher.Application") try { launcherClass.hookBeforeMethod("isShouldBlur") { it.result = false } blurUtilsClass.hookBeforeMethod("fastBlurWhenOpenOrCloseFolder", launcherClass, Boolean::class.java) { it.result = null } } catch (e: Exception) { XposedLogUtils.logE(TAG, e) } var isShouldBlur = false launcherClass.hookAfterMethod("openFolder", folderInfo, View::class.java) { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity val isInNormalEditing = mLauncher.callMethod("isInNormalEditing") as Boolean if (!isInNormalEditing) blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true) } launcherClass.hookAfterMethod("isFolderShowing") { isShouldBlur = it.result as Boolean } launcherClass.hookAfterMethod("closeFolder", Boolean::class.java) { isShouldBlur = false val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity val isInNormalEditing = mLauncher.callMethod("isInNormalEditing") as Boolean if (isInNormalEditing) blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 0L) else blurUtilsClass.callStaticMethod("fastBlur", 0.0f, mLauncher.window, true) } launcherClass.hookAfterMethod("cancelShortcutMenu", Int::class.java, cancelShortcutMenuReasonClass) { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity if (isShouldBlur) blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 0L) } launcherClass.hookBeforeMethod("onGesturePerformAppToHome") { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity if (isShouldBlur) { blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 0L) } } blurUtilsClass.hookBeforeAllMethods("fastBlurWhenStartOpenOrCloseApp") { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity val isInEditing = mLauncher.callMethod("isInEditing") as Boolean if (isShouldBlur) it.result = blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 0L) else if (isInEditing) it.result = blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 0L) } blurUtilsClass.hookBeforeAllMethods("fastBlurWhenFinishOpenOrCloseApp") { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity val isInEditing = mLauncher.callMethod("isInEditing") as Boolean if (isShouldBlur) it.result = blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 0L) else if (isInEditing) it.result = blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 0L) } blurUtilsClass.hookAfterAllMethods("fastBlurWhenEnterRecents") { it.args[0]?.callMethod("hideShortcutMenuWithoutAnim") } blurUtilsClass.hookAfterAllMethods("fastBlurWhenExitRecents") { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity val isInEditing = mLauncher.callMethod("isInEditing") as Boolean if (isShouldBlur) it.result = blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 0L) else if (isInEditing) it.result = blurUtilsClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 0L) } blurUtilsClass.hookBeforeAllMethods("fastBlurDirectly") { val blurRatio = it.args[0] as Float if (isShouldBlur && blurRatio == 0.0f) it.result = null } if (((mPrefsMap.getStringAsInt("home_recent_blur_level", 6) == 0) && (mPrefsMap.getStringAsInt("home_recent_blur_level", 6) != 5)) || (mPrefsMap.getStringAsInt("home_recent_blur_level", 6) != 0) ) { navStubViewClass.hookBeforeMethod("appTouchResolution", MotionEvent::class.java) { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity if (isShouldBlur) { blurUtilsClass.callStaticMethod("fastBlurDirectly", 1.0f, mLauncher.window) } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/FolderColumns.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder import android.view.ViewGroup import android.widget.GridView import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.hookAfterAllMethods import de.robv.android.xposed.XposedHelpers object FolderColumns : BaseHook() { override fun init() { val value = mPrefsMap.getInt("home_folder_columns", 3) if (value == 3) return "com.miui.home.launcher.Folder".findClass().hookAfterAllMethods( "bind" ) { val columns: Int = value val mContent = XposedHelpers.getObjectField(it.thisObject, "mContent") as GridView mContent.numColumns = columns if (mPrefsMap.getBoolean("home_folder_width") && (columns > 3)) { mContent.setPadding(0, 0, 0, 0) val lp = mContent.layoutParams lp.width = ViewGroup.LayoutParams.MATCH_PARENT mContent.layoutParams = lp } if (columns > 3) { val mBackgroundView = XposedHelpers.getObjectField(it.thisObject, "mBackgroundView") as ViewGroup mBackgroundView.setPadding( mBackgroundView.paddingLeft / 3, mBackgroundView.paddingTop, mBackgroundView.paddingRight / 3, mBackgroundView.paddingBottom ) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/FolderShade.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder; import android.content.Context; import android.graphics.LinearGradient; import android.graphics.Shader; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.PaintDrawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.RectShape; import android.os.Handler; import android.view.View; import androidx.annotation.NonNull; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.PrefsUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedHelpers; public class FolderShade extends BaseHook { private Class mWallpaperUtilsCls = null; private boolean isLight = false; @Override public void init() { mWallpaperUtilsCls = XposedHelpers.findClassIfExists("com.miui.home.launcher.WallpaperUtils", lpparam.classLoader); MethodHook hook = new MethodHook() { @Override protected void after(MethodHookParam param) { View folder = (View) param.thisObject; new Thread(() -> { try { Context context = folder.getContext(); int opt = Integer.parseInt(PrefsUtils.getSharedStringPrefs(context, "prefs_key_home_folder_shade", "0")); int level = PrefsUtils.getSharedIntPrefs(context, "prefs_key_home_folder_shade_level", 40); if (mWallpaperUtilsCls != null) { try { isLight = (boolean) XposedHelpers.callStaticMethod(mWallpaperUtilsCls, "hasAppliedLightWallpaper"); } catch (Throwable tr) { XposedLogUtils.logW(TAG, "isLight is abnormal", tr); } } Drawable bkg; if (opt == 1) { int bgColor = (isLight ? 0x00ffffff : 0x00000000) | (Math.round(255 * level / 100f) * 0x1000000); bkg = new ColorDrawable(bgColor); } else if (opt == 2) { bkg = getPaintDrawable(level); } else { bkg = null; } new Handler(context.getMainLooper()).post(() -> { XposedInit.mPrefsMap.put("prefs_key_home_folder_shade", String.valueOf(opt)); XposedInit.mPrefsMap.put("prefs_key_home_folder_shade_level", level); folder.setBackground(bkg); }); } catch (Throwable t) { XposedLogUtils.logW(TAG, "", t); } }).start(); } }; hookAllConstructors("com.miui.home.launcher.FolderCling", hook); findAndHookMethod("com.miui.home.launcher.FolderCling", "onWallpaperColorChanged", hook); findAndHookMethod("com.miui.home.launcher.FolderCling", "updateLayout", boolean.class, hook); findAndHookMethod("com.miui.home.launcher.Folder", "setBackgroundAlpha", float.class, new MethodHook() { @Override protected void after(MethodHookParam param) { int opt = mPrefsMap.getStringAsInt("home_folder_shade", 0); Object mLauncher = XposedHelpers.getObjectField(param.thisObject, "mLauncher"); View folderCling = (View) XposedHelpers.callMethod(mLauncher, "getFolderCling"); if (opt == 1 || mLauncher == null || folderCling == null) return; Drawable bkg = folderCling.getBackground(); if (bkg != null) bkg.setAlpha(Math.round((float) param.args[0] * 255)); } }); } @NonNull private PaintDrawable getPaintDrawable(int level) { PaintDrawable pd = new PaintDrawable(); pd.setShape(new RectShape()); pd.setShaderFactory(new ShapeDrawable.ShaderFactory() { @Override public Shader resize(int width, int height) { int bgColor1 = (isLight ? 0x00ffffff : 0x00000000) | (Math.round(255 / 6f * level / 100f) * 0x1000000); int bgColor2 = (isLight ? 0x00ffffff : 0x00000000) | (Math.round(255 * level / 100f) * 0x1000000); return new LinearGradient( 0, 0, 0, height, new int[]{bgColor1, bgColor2, bgColor2, bgColor1}, new float[]{0.0f, 0.25f, 0.65f, 1.0f}, Shader.TileMode.CLAMP ); } }); return pd; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/FolderVerticalPadding.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder import android.widget.GridView import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.dp2px import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.hookAfterAllMethods import de.robv.android.xposed.XposedHelpers object FolderVerticalPadding : BaseHook() { override fun init() { val verticalPadding = mPrefsMap.getInt("home_folder_vertical_padding", 0) if (verticalPadding <= 0) return "com.miui.home.launcher.Folder".findClass().hookAfterAllMethods( "bind" ) { val mContent = XposedHelpers.getObjectField(it.thisObject, "mContent") as GridView mContent.verticalSpacing = dp2px(verticalPadding.toFloat()) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/folder/SmallFolderIconBlur.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.folder; import android.content.Context; import android.os.Build; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import com.sevtinge.cemiuiler.utils.DisplayUtils; import de.robv.android.xposed.XposedHelpers; public class SmallFolderIconBlur extends BaseHook { boolean isShowEditPanel; Class mLauncher; Class mFolderInfo; Class mFolderIcon; Class mFolderIcon1x1; Class mLauncherState; Class mDragView; int mFolderIconSize; ImageView mIconImageView; @Override public void init() { mLauncher = findClassIfExists("com.miui.home.launcher.Launcher"); mFolderInfo = findClassIfExists("com.miui.home.launcher.FolderInfo"); mFolderIcon = findClassIfExists("com.miui.home.launcher.FolderIcon"); mFolderIcon1x1 = findClassIfExists("com.miui.home.launcher.folder.FolderIcon1x1"); mLauncherState = findClassIfExists("com.miui.home.launcher.LauncherState"); mDragView = findClassIfExists("com.miui.home.launcher.DragView"); hookAllConstructors(mFolderIcon, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); try { mIconImageView = (ImageView) XposedHelpers.getObjectField(param.thisObject, "mImageView"); } catch (Exception e) { mIconImageView = (ImageView) XposedHelpers.getObjectField(param.thisObject, "mIconImageView"); } FrameLayout mDockBlur = (FrameLayout) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mDockBlur"); if (mDockBlur != null) return; mDockBlur = new FrameLayout(mContext); XposedHelpers.setAdditionalInstanceField(param.thisObject, "mDockBlur", mDockBlur); } }); MethodHook mDockBlur = new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { try { mIconImageView = (ImageView) XposedHelpers.getObjectField(param.thisObject, "mImageView"); } catch (Exception e) { mIconImageView = (ImageView) XposedHelpers.getObjectField(param.thisObject, "mIconImageView"); } Context mContext = mIconImageView.getContext(); mFolderIconSize = DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_small_folder_icon_bg_size", 56)); FrameLayout mIconContainer = (FrameLayout) mIconImageView.getParent(); FrameLayout mDockBlur = (FrameLayout) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mDockBlur"); FrameLayout view = new FrameLayout(mContext); mIconImageView.setVisibility(View.GONE); mDockBlur.addView(view); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { new BlurUtils(mDockBlur, "home_small_folder_icon_bg_custom"); } mIconContainer.addView(mDockBlur, 0); FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mDockBlur.getLayoutParams(); lp.gravity = Gravity.CENTER; lp.height = mFolderIconSize; lp.width = mFolderIconSize; findAndHookMethod(mLauncher, "showEditPanel", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { isShowEditPanel = (boolean) param.args[0]; if (isShowEditPanel) { mDockBlur.setVisibility(View.GONE); mIconImageView.setVisibility(View.VISIBLE); } else { mDockBlur.setVisibility(View.VISIBLE); mIconImageView.setVisibility(View.GONE); } } }); findAndHookMethod(mLauncher, "openFolder", mFolderInfo, View.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { mDockBlur.setVisibility(View.GONE); } }); findAndHookMethod(mLauncher, "closeFolder", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { if (!isShowEditPanel) mDockBlur.setVisibility(View.VISIBLE); } }); findAndHookMethod(mLauncher, "onStateSetStart", mLauncherState, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { if (param.args[0].getClass().getSimpleName().equals("LauncherState")) { mDockBlur.setVisibility(View.VISIBLE); } else { mDockBlur.setVisibility(View.GONE); } } }); } }; try { findAndHookMethod(mFolderIcon1x1, "onFinishInflate", mDockBlur); } catch (Exception e) { findAndHookMethod(mFolderIcon, "onFinishInflate", mDockBlur); } /*hookAllMethods(mDragView, "showWithAnim", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { View dragView = (View) param.thisObject; dragView.setLayerType(View.LAYER_TYPE_HARDWARE, null); Object mDragInfo = XposedHelpers.getObjectField(param.thisObject, "mDragInfo"); } });*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/gesture/DoubleTap.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.gesture; import android.content.Context; import android.os.SystemClock; import android.view.MotionEvent; import android.view.ViewConfiguration; import com.sevtinge.cemiuiler.module.app.GlobalActions; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class DoubleTap extends BaseHook { Class mWorkspace; @Override public void init() { mWorkspace = findClassIfExists("com.miui.home.launcher.Workspace"); hookAllConstructors(mWorkspace, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Object mDoubleTapControllerEx = XposedHelpers.getAdditionalInstanceField(param.thisObject, "mDoubleTapControllerEx"); if (mDoubleTapControllerEx != null) return; mDoubleTapControllerEx = new DoubleTapController((Context) param.args[0], "prefs_key_home_gesture_double_tap"); XposedHelpers.setAdditionalInstanceField(param.thisObject, "mDoubleTapControllerEx", mDoubleTapControllerEx); } }); findAndHookMethod(mWorkspace, "dispatchTouchEvent", MotionEvent.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { DoubleTapController mDoubleTapControllerEx = (DoubleTapController) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mDoubleTapControllerEx"); if (mDoubleTapControllerEx == null) return; if (!mDoubleTapControllerEx.isDoubleTapEvent((MotionEvent) param.args[0])) return; int mCurrentScreenIndex = XposedHelpers.getIntField(param.thisObject, lpparam.packageName.equals("com.miui.home") ? "mCurrentScreenIndex" : "mCurrentScreen"); Object cellLayout = XposedHelpers.callMethod(param.thisObject, "getCellLayout", mCurrentScreenIndex); if ((boolean) XposedHelpers.callMethod(cellLayout, "lastDownOnOccupiedCell")) return; if ((boolean) XposedHelpers.callMethod(param.thisObject, "isInNormalEditingMode")) return; mDoubleTapControllerEx.onDoubleTapEvent(); } }); } public static class DoubleTapController { private float mActionDownRawX; private float mActionDownRawY; private int mClickCount; public final Context mContext; private final String mActionKey; private float mFirstClickRawX; private float mFirstClickRawY; private long mLastClickTime; private final int mTouchSlop; DoubleTapController(Context context, String actionKey) { this.mContext = context; this.mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2; this.mActionKey = actionKey; } boolean isDoubleTapEvent(MotionEvent motionEvent) { int action = motionEvent.getActionMasked(); if (action == MotionEvent.ACTION_DOWN) { this.mActionDownRawX = motionEvent.getRawX(); this.mActionDownRawY = motionEvent.getRawY(); return false; } else if (action != MotionEvent.ACTION_UP) { return false; } else { float rawX = motionEvent.getRawX(); float rawY = motionEvent.getRawY(); if (Math.abs(rawX - this.mActionDownRawX) <= ((float) this.mTouchSlop) && Math.abs(rawY - this.mActionDownRawY) <= ((float) this.mTouchSlop)) { long MAX_DURATION = 500; if (SystemClock.elapsedRealtime() - this.mLastClickTime > MAX_DURATION || rawY - this.mFirstClickRawY > (float) this.mTouchSlop || rawX - this.mFirstClickRawX > (float) this.mTouchSlop) { this.mClickCount = 0; } this.mClickCount++; if (this.mClickCount == 1) { this.mFirstClickRawX = rawX; this.mFirstClickRawY = rawY; this.mLastClickTime = SystemClock.elapsedRealtime(); return false; } else if (Math.abs(rawY - this.mFirstClickRawY) <= ((float) this.mTouchSlop) && Math.abs(rawX - this.mFirstClickRawX) <= ((float) this.mTouchSlop) && SystemClock.elapsedRealtime() - this.mLastClickTime <= MAX_DURATION) { this.mClickCount = 0; return true; } } this.mClickCount = 0; return false; } } void onDoubleTapEvent() { GlobalActions.handleAction(mContext, mActionKey); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/gesture/DoubleTapController.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.gesture import android.content.Context import android.os.SystemClock import android.view.MotionEvent import android.view.ViewConfiguration class DoubleTapController internal constructor(mContext: Context) { private val maxDuration: Long = 500 private var mActionDownRawX: Float = 0f private var mActionDownRawY: Float = 0f private var mClickCount: Int = 0 private var mFirstClickRawX: Float = 0f private var mFirstClickRawY: Float = 0f private var mLastClickTime: Long = 0 private val mTouchSlop: Int = ViewConfiguration.get(mContext).scaledTouchSlop * 2 fun isDoubleTapEvent(motionEvent: MotionEvent): Boolean { val action = motionEvent.actionMasked return when { action == MotionEvent.ACTION_DOWN -> { mActionDownRawX = motionEvent.rawX mActionDownRawY = motionEvent.rawY false } action != MotionEvent.ACTION_UP -> false else -> { val rawX = motionEvent.rawX val rawY = motionEvent.rawY if (kotlin.math.abs(rawX - mActionDownRawX) <= mTouchSlop.toFloat() && kotlin.math.abs( rawY - mActionDownRawY ) <= mTouchSlop.toFloat() ) { if (SystemClock.elapsedRealtime() - mLastClickTime > maxDuration || rawY - mFirstClickRawY > mTouchSlop.toFloat() || rawX - mFirstClickRawX > mTouchSlop.toFloat()) mClickCount = 0 mClickCount++ if (mClickCount == 1) { mFirstClickRawX = rawX mFirstClickRawY = rawY mLastClickTime = SystemClock.elapsedRealtime() return false } else if (kotlin.math.abs(rawY - mFirstClickRawY) <= mTouchSlop.toFloat() && kotlin.math.abs( rawX - mFirstClickRawX ) <= mTouchSlop.toFloat() && SystemClock.elapsedRealtime() - mLastClickTime <= maxDuration ) { mClickCount = 0 return true } } mClickCount = 0 false } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/gesture/HotSeatSwipe.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.gesture; import android.content.Context; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.ViewGroup; import com.sevtinge.cemiuiler.module.app.GlobalActions; import com.sevtinge.cemiuiler.module.base.BaseHook; public class HotSeatSwipe extends BaseHook { private GestureDetector mDetectorHorizontal; @Override public void init() { findAndHookMethod("com.miui.home.launcher.hotseats.HotSeats", "dispatchTouchEvent", MotionEvent.class, new MethodHook() { @Override protected void before(final MethodHookParam param) throws Throwable { MotionEvent ev = (MotionEvent) param.args[0]; if (ev == null) return; ViewGroup hotSeat = (ViewGroup) param.thisObject; Context helperContext = hotSeat.getContext(); if (helperContext == null) return; if (mDetectorHorizontal == null) mDetectorHorizontal = new GestureDetector(helperContext, new SwipeListenerHorizontal(hotSeat)); mDetectorHorizontal.onTouchEvent(ev); } }); } private static class SwipeListenerHorizontal extends GestureDetector.SimpleOnGestureListener { private final int SWIPE_MIN_DISTANCE_HORIZ; private final int SWIPE_THRESHOLD_VELOCITY; final Context helperContext; SwipeListenerHorizontal(Object cellLayout) { helperContext = ((ViewGroup) cellLayout).getContext(); float density = helperContext.getResources().getDisplayMetrics().density; SWIPE_MIN_DISTANCE_HORIZ = Math.round(75 * density); SWIPE_THRESHOLD_VELOCITY = Math.round(33 * density); } @Override public boolean onDown(MotionEvent e) { return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e1 == null || e2 == null) return false; if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE_HORIZ && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) return GlobalActions.handleAction(helperContext, "prefs_key_home_gesture_right_swipe"); if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE_HORIZ && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) return GlobalActions.handleAction(helperContext, "prefs_key_home_gesture_left_swipe"); return false; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/gesture/QuickBack.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.gesture; import com.sevtinge.cemiuiler.module.base.BaseHook; public class QuickBack extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.recents.GestureStubView", "isDisableQuickSwitch", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(false); } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/gesture/ShakeDevice.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.gesture; import android.app.Activity; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorManager; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.ShakeManager; import de.robv.android.xposed.XposedHelpers; public class ShakeDevice extends BaseHook { @Override public void init() { final String shakeMgrKey = "MIUIZER_SHAKE_MGR"; findAndHookMethod("com.miui.home.launcher.Launcher", "onResume", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { ShakeManager shakeMgr = (ShakeManager) XposedHelpers.getAdditionalInstanceField(param.thisObject, shakeMgrKey); if (shakeMgr == null) { shakeMgr = new ShakeManager((Context) param.thisObject); XposedHelpers.setAdditionalInstanceField(param.thisObject, shakeMgrKey, shakeMgr); } Activity launcherActivity = (Activity) param.thisObject; SensorManager sensorMgr = (SensorManager) launcherActivity.getSystemService(Context.SENSOR_SERVICE); shakeMgr.reset(); sensorMgr.registerListener(shakeMgr, sensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); } }); findAndHookMethod("com.miui.home.launcher.Launcher", "onPause", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { if (XposedHelpers.getAdditionalInstanceField(param.thisObject, shakeMgrKey) == null) return; Activity launcherActivity = (Activity) param.thisObject; SensorManager sensorMgr = (SensorManager) launcherActivity.getSystemService(Context.SENSOR_SERVICE); sensorMgr.unregisterListener((ShakeManager) XposedHelpers.getAdditionalInstanceField(param.thisObject, shakeMgrKey)); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/gesture/SwipeAndStop.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.gesture; import static com.sevtinge.cemiuiler.utils.Helpers.findAndHookMethodUseUnhook; import android.content.Context; import android.os.Bundle; import com.sevtinge.cemiuiler.module.app.GlobalActions; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class SwipeAndStop extends BaseHook { @Override public void init() { Class VibratorCls = findClassIfExists("android.os.Vibrator", lpparam.classLoader); hookAllMethods("com.miui.home.recents.GestureBackArrowView", "setReadyFinish", new MethodHook() { private Unhook vibratorHook = null; @Override protected void before(MethodHookParam param) throws Throwable { vibratorHook = findAndHookMethodUseUnhook(VibratorCls, "vibrate", long.class, XC_MethodReplacement.DO_NOTHING); } @Override protected void after(MethodHookParam param) throws Throwable { if (vibratorHook != null) { vibratorHook.unhook(); } } }); findAndHookMethod("com.miui.home.recents.GestureStubView", "disableQuickSwitch", boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.args[0] = false; } }); findAndHookMethod("com.miui.home.recents.GestureStubView", "isDisableQuickSwitch", XC_MethodReplacement.returnConstant(false)); findAndHookMethod("com.miui.home.recents.GestureStubView","getNextTask", Context.class, boolean.class, int.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { boolean switchApp = (boolean) param.args[1]; if (switchApp) { Context mContext = (Context) param.args[0]; Bundle bundle = new Bundle(); bundle.putInt("inDirection", (int)param.args[2]); if (GlobalActions.handleAction(mContext, "pref_key_controls_fsg_swipeandstop")) { Class Task = findClassIfExists("com.android.systemui.shared.recents.model.Task", lpparam.classLoader); param.setResult(XposedHelpers.newInstance(Task)); return; } } param.setResult(null); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/layout/HotSeatsHeight.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.layout; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DisplayUtils; public class HotSeatsHeight extends BaseHook { Class mDeviceConfig; @Override public void init() { mDeviceConfig = findClassIfExists("com.miui.home.launcher.DeviceConfig"); findAndHookMethod(mDeviceConfig, "calcHotSeatsHeight", Context.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Context context = (Context) param.args[0]; param.setResult(DisplayUtils.dip2px(context, mPrefsMap.getInt("home_layout_hotseats_height", 60))); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/layout/HotSeatsMarginBottom.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.layout; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DisplayUtils; public class HotSeatsMarginBottom extends BaseHook { Class mDeviceConfig; @Override public void init() { mDeviceConfig = findClassIfExists("com.miui.home.launcher.DeviceConfig"); findAndHookMethod(mDeviceConfig, "calcHotSeatsMarginBottom", Context.class, boolean.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Context context = (Context) param.args[0]; param.setResult(DisplayUtils.dip2px(context, mPrefsMap.getInt("home_layout_hotseats_margin_bottom", 60))); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/layout/HotSeatsMarginTop.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.layout; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DisplayUtils; public class HotSeatsMarginTop extends BaseHook { Class mDeviceConfig; @Override public void init() { mDeviceConfig = findClassIfExists("com.miui.home.launcher.DeviceConfig"); findAndHookMethod(mDeviceConfig, "calcHotSeatsMarginTop", Context.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Context context = (Context) param.args[0]; param.setResult(DisplayUtils.dip2px(context, mPrefsMap.getInt("home_layout_hotseats_margin_top", 60))); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/layout/SearchBarMarginBottom.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.layout; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DisplayUtils; public class SearchBarMarginBottom extends BaseHook { Class mDeviceConfig; @Override public void init() { mDeviceConfig = findClassIfExists("com.miui.home.launcher.DeviceConfig"); findAndHookMethod(mDeviceConfig, "calcSearchBarMarginBottom", Context.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Context context = (Context) param.args[0]; param.setResult(DisplayUtils.dip2px(context, mPrefsMap.getInt("home_layout_searchbar_margin_bottom", 0))); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/layout/ShowClock.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.layout; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class ShowClock extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.launcher.Workspace", "isScreenHasClockGadget", long.class, XC_MethodReplacement.returnConstant(false)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/layout/UnlockGrids.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.layout; import android.content.Context; import android.os.Bundle; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import java.util.ArrayList; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class UnlockGrids extends BaseHook { Class mDeviceConfig; @Override public void init() { /* mDeviceConfig = findClassIfExists("com.miui.home.launcher.DeviceConfig"); hookAllMethodsSilently("com.miui.home.launcher.compat.LauncherCellCountCompatDevice", "shouldUseDeviceValue", XC_MethodReplacement.returnConstant(false)); findAndHookMethod("com.miui.home.settings.MiuiHomeSettings", "onCreatePreferences", Bundle.class, String.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "mScreenCellsConfig"), "setVisible", true); } }); findAndHookMethod(mDeviceConfig, "loadCellsCountConfig", Context.class, boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { int sCellCountY = (int) XposedHelpers.getStaticObjectField(mDeviceConfig, "sCellCountY"); if (sCellCountY > 6) { int cellHeight = (int) XposedHelpers.callStaticMethod(mDeviceConfig, "getCellHeight"); XposedHelpers.setStaticObjectField(mDeviceConfig, "sFolderCellHeight", cellHeight); } } }); UnlockGridsRes(); */ hookAllMethodsSilently("com.miui.home.launcher.compat.LauncherCellCountCompatDevice", "shouldUseDeviceValue", XC_MethodReplacement.returnConstant(false)); findAndHookMethod("com.miui.home.settings.MiuiHomeSettings", "onCreatePreferences", Bundle.class, String.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "mScreenCellsConfig"), "setVisible", true); } }); Class DeviceConfigClass = XposedHelpers.findClass("com.miui.home.launcher.DeviceConfig", lpparam.classLoader); Helpers.findAndHookMethod(DeviceConfigClass, "loadCellsCountConfig", Context.class, boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { int sCellCountY = (int) XposedHelpers.getStaticObjectField(DeviceConfigClass, "sCellCountY"); if (sCellCountY > 6) { int cellHeight = (int) XposedHelpers.callStaticMethod(DeviceConfigClass, "getCellHeight"); XposedHelpers.setStaticObjectField(DeviceConfigClass, "sFolderCellHeight", cellHeight); } } }); findAndHookMethod("com.miui.home.launcher.ScreenUtils", "getScreenCellsSizeOptions", Context.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { ArrayList arrayList = new ArrayList<>(); int cellCountXMin = 3; int cellCountXMax = 16; int cellCountYMin = 4; int cellCountYMax = 18; while (cellCountXMin <= cellCountXMax) { for (int i = cellCountYMin; i <= cellCountYMax; i++) { arrayList.add(cellCountXMin + "x" + i); } cellCountXMin++; } param.setResult(arrayList); } }); Helpers.findAndHookMethod("com.miui.home.launcher.compat.LauncherCellCountCompatNoWord", lpparam.classLoader, "setLoadResCellConfig", boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.args[0] = true; } }); Helpers.hookAllMethods("com.miui.home.launcher.DeviceConfig", lpparam.classLoader, "isCellSizeChangedByTheme", new MethodHook() { XC_MethodHook.Unhook nowordHook; @Override protected void before(MethodHookParam param) throws Throwable { nowordHook = Helpers.findAndHookMethodUseUnhook("com.miui.home.launcher.common.Utilities", lpparam.classLoader, "isNoWordModel", XC_MethodReplacement.returnConstant(false)); } @Override protected void after(MethodHookParam param) throws Throwable { if (nowordHook != null) nowordHook.unhook(); nowordHook = null; } }); UnlockGridsRes(); } public void UnlockGridsRes() { mResHook.setObjectReplacement("com.miui.home", "integer", "config_cell_count_x", 3); mResHook.setObjectReplacement("com.miui.home", "integer", "config_cell_count_y", 4); mResHook.setObjectReplacement("com.miui.home", "integer", "config_cell_count_x_min", 3); mResHook.setObjectReplacement("com.miui.home", "integer", "config_cell_count_y_min", 4); mResHook.setObjectReplacement("com.miui.home", "integer", "config_cell_count_x_max", 16); mResHook.setObjectReplacement("com.miui.home", "integer", "config_cell_count_y_max", 18); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/layout/UnlockGridsNoWord.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.layout; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class UnlockGridsNoWord extends BaseHook { Class mDeviceConfig; @Override public void init() { mDeviceConfig = findClassIfExists("com.miui.home.launcher.DeviceConfig"); findAndHookMethod(mDeviceConfig, "isThemeCoverCellConfig", XC_MethodReplacement.returnConstant(true)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/layout/WorkspacePadding.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.layout; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DisplayUtils; public class WorkspacePadding extends BaseHook { Context mContext; Class mDeviceConfig; @Override public void init() { mDeviceConfig = findClassIfExists("com.miui.home.launcher.DeviceConfig"); findAndHookMethod(mDeviceConfig, "Init", Context.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) { mContext = (Context) param.args[0]; } }); if (mPrefsMap.getBoolean("home_layout_workspace_padding_bottom_enable")) { findAndHookMethod(mDeviceConfig, "getWorkspaceCellPaddingBottom", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_layout_workspace_padding_bottom", 0))); } }); } if (mPrefsMap.getBoolean("home_layout_workspace_padding_top_enable")) { try { // 新版本桌面,先标记,后续再做进一步修改 findAndHookMethod(mDeviceConfig, "getWorkspaceCellPaddingTop", Context.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_layout_workspace_padding_top", 0))); } }); } catch (Throwable t) { findAndHookMethod(mDeviceConfig, "getWorkspaceCellPaddingTop", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(DisplayUtils.dip2px(mContext, mPrefsMap.getInt("home_layout_workspace_padding_top", 0))); } }); } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/mipad/EnableHideGestureLine.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.mipad import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object EnableHideGestureLine : BaseHook() { override fun init() { loadClass("com.miui.home.recents.settings.NavigationBarTypePreferenceFragment").methodFinder().first{ name == "updatePreferenceVisibility" }.createHook{ before{ it.result = true } } loadClass("com.miui.home.recents.BaseRecentsImpl").methodFinder().first{ name == "initHideGestureLine" }.createHook{ before{ it.result = null } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/mipad/EnableMoreSetting.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.mipad import android.view.View import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.getObjectField object EnableMoreSetting : BaseHook() { override fun init() { loadClass("com.miui.home.settings.MiuiHomeSettings").methodFinder().first{ name == "checkDevice" }.createHook{ returnConstant(true) } loadClass("com.miui.home.launcher.DeviceConfig").methodFinder().first{ name == "needShowCellsEntry" }.createHook{ returnConstant(true) } loadClass("com.miui.home.launcher.LauncherMenu").methodFinder().first{ name == "onShow" }.createHook{ after{ val mDefaultScreenPreview = it.thisObject.getObjectField("mDefaultScreenPreview") as View mDefaultScreenPreview.visibility = View.VISIBLE } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/mipad/SetGestureNeedFingerNum.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.mipad import android.view.MotionEvent import com.github.kyuubiran.ezxhelper.ClassUtils.getStaticObjectOrNullAs import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object SetGestureNeedFingerNum : BaseHook() { override fun init() { val clazzGestureOperationHelper = loadClass("com.miui.home.recents.GestureOperationHelper") clazzGestureOperationHelper.methodFinder() .filterByName("isThreePointerSwipeLeftOrRightInScreen") .filterByParamTypes(MotionEvent::class.java, Int::class.java) .first().createHook { before { param -> val motionEvent = param.args[0] as MotionEvent val swipeFlag = param.args[1] as Int val flagSwipeLeft = getStaticObjectOrNullAs(clazzGestureOperationHelper, "SWIPE_DIRECTION_LEFT") val flagSwipeRight = getStaticObjectOrNullAs(clazzGestureOperationHelper, "SWIPE_DIRECTION_RIGHT") val flagsSwipeLeftAndRight = setOf(flagSwipeLeft, flagSwipeRight) val z = if (motionEvent.device == null) true else motionEvent.device.sources and 4098 == 4098 param.result = z && (swipeFlag in flagsSwipeLeftAndRight) && motionEvent.pointerCount == 4 } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/navigation/BackGestureAreaHeight.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.navigation; import android.view.WindowManager; import com.sevtinge.cemiuiler.module.base.BaseHook; public class BackGestureAreaHeight extends BaseHook { @Override public void init() { findAndHookMethodSilently("com.miui.home.recents.GestureStubView", "getGestureStubWindowParam", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { WindowManager.LayoutParams lp = (WindowManager.LayoutParams)param.getResult(); int pct = mPrefsMap.getInt("home_navigation_back_area_height", 60); //记得改key lp.height = Math.round(lp.height / 60.0f * pct); param.setResult(lp); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/navigation/BackGestureAreaWidth.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.navigation; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class BackGestureAreaWidth extends BaseHook { @Override public void init() { findAndHookMethodSilently("com.miui.home.recents.GestureStubView", "initScreenSizeAndDensity", int.class, new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { int pct = mPrefsMap.getInt("home_navigation_back_area_width", 100); if (pct == 100) return; int mGestureStubDefaultSize = XposedHelpers.getIntField(param.thisObject, "mGestureStubDefaultSize"); int mGestureStubSize = XposedHelpers.getIntField(param.thisObject, "mGestureStubSize"); mGestureStubDefaultSize = Math.round(mGestureStubDefaultSize * pct / 100f); mGestureStubSize = Math.round(mGestureStubSize * pct / 100f); XposedHelpers.setIntField(param.thisObject, "mGestureStubDefaultSize", mGestureStubDefaultSize); XposedHelpers.setIntField(param.thisObject, "mGestureStubSize", mGestureStubSize); } }); findAndHookMethodSilently("com.miui.home.recents.GestureStubView", "setSize", int.class, new MethodHook() { @Override protected void before(final MethodHookParam param) throws Throwable { int pct = mPrefsMap.getInt("home_navigation_back_area_width", 100); if (pct == 100) return; int mGestureStubDefaultSize = XposedHelpers.getIntField(param.thisObject, "mGestureStubDefaultSize"); if ((int)param.args[0] == mGestureStubDefaultSize) return; param.args[0] = Math.round((int)param.args[0] * pct / 100f); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/AlwaysBlurWallpaper.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object AlwaysBlurWallpaper : BaseHook() { override fun init() { // if (!mPrefsMap.getBoolean("home_blur_wallpaper")) return val value = mPrefsMap.getInt("home_blur_radius", 100) loadClass("com.miui.home.launcher.common.BlurUtils").methodFinder().first { name == "fastBlur" && parameterCount == 4 }.createHook { before { it.args[0] = value.toFloat() / 100 it.args[2] = true } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/AlwaysShowStatusClock.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object AlwaysShowStatusClock : BaseHook() { override fun init() { // if (!mPrefsMap.getBoolean("home_show_status_clock")) return val mWorkspaceClass = loadClass("com.miui.home.launcher.Workspace") val methodNames = listOf("isScreenHasClockGadget", "isScreenHasClockWidget", "isClockWidget") methodNames.forEach { methodName -> val result = runCatching { mWorkspaceClass.methodFinder().first { name == methodName }.createHook { before { it.result = false } } } if (result.isSuccess) return@forEach } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/BlurRadius.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.hookBeforeAllMethods object BlurRadius : BaseHook() { override fun init() { val value = mPrefsMap.getInt("home_other_blur_radius", 100).toFloat() / 100 if (value == 1f) return val blurUtilsClass = "com.miui.home.launcher.common.BlurUtils".findClass() blurUtilsClass.hookBeforeAllMethods("fastBlur") { it.args[0] = it.args[0] as Float * value } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/BlurWhenShowShortcutMenu.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator import android.graphics.RenderEffect import android.graphics.Shader import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.graphics.drawable.ShapeDrawable import android.os.Build import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.annotation.RequiresApi import androidx.core.view.ViewCompat.animate import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.HookUtils import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import kotlin.math.sqrt object BlurWhenShowShortcutMenu : BaseHook() { override fun init() { val shortcutMenuBackgroundAlpha = mPrefsMap.getInt("home_other_shortcut_background_blur_custom", 200) val shortcutMenuLayerClass: Class<*> = findClassIfExists("com.miui.home.launcher.ShortcutMenuLayer") val shortcutMenuClass: Class<*> = findClassIfExists("com.miui.home.launcher.shortcuts.ShortcutMenu") val blurUtilsClass: Class<*> = findClassIfExists("com.miui.home.launcher.common.BlurUtils") val applicationClass: Class<*> = findClassIfExists("com.miui.home.launcher.Application") val utilitiesClass: Class<*> = findClassIfExists("com.miui.home.launcher.common.Utilities") val dragViewClass: Class<*> = findClassIfExists("com.miui.home.launcher.DragView") val allBluredDrawable: MutableList = ArrayList() val singleLayerAlpha = ((1.0 - sqrt(1.0 - (shortcutMenuBackgroundAlpha / 255.0))) * 255.0).toInt() var isShortcutMenuLayerBlurred = false var targetView: ViewGroup? = null var dragView: View? = null var blurBackground = true fun showBlurDrawable() { allBluredDrawable.forEach { drawable -> XposedHelpers.callMethod(drawable, "setVisible", true, false) } } fun hideBlurDrawable() { allBluredDrawable.forEach { drawable -> XposedHelpers.callMethod(drawable, "setVisible", false, false) } } XposedBridge.hookAllMethods( shortcutMenuLayerClass, "showShortcutMenu", object : XC_MethodHook() { @RequiresApi(Build.VERSION_CODES.S) override fun beforeHookedMethod(param: MethodHookParam) { val dragObject = param.args[0] val dragViewInfo = XposedHelpers.callMethod(dragObject, "getDragInfo") val iconIsInFolder = XposedHelpers.callMethod(dragViewInfo, "isInFolder") as Boolean val mLauncher = XposedHelpers.callStaticMethod(applicationClass, "getLauncher") val systemUiController = XposedHelpers.callMethod(mLauncher, "getSystemUiController") val mWindow = HookUtils.getValueByField(systemUiController, "mWindow") val targetBlurView = XposedHelpers.callMethod(mLauncher, "getScreen") as View // 修复文件夹内各种模糊冲突异常 blurBackground = if (iconIsInFolder) !mPrefsMap.getBoolean("home_folder_blur") else true val renderEffectArray = arrayOfNulls(51) for (index in 0..50) { renderEffectArray[index] = RenderEffect.createBlurEffect( (index + 1).toFloat(), (index + 1).toFloat(), Shader.TileMode.MIRROR ) } val valueAnimator = ValueAnimator.ofInt(0, 50) valueAnimator.addUpdateListener { animator -> val value = animator.animatedValue as Int targetBlurView.setRenderEffect(renderEffectArray[value]) // 修复始终模糊壁纸冲突导致的各种模糊异常 if (blurBackground && !mPrefsMap.getBoolean("home_other_always_blur_launcher_wallpaper")) { XposedHelpers.callStaticMethod( blurUtilsClass, "fastBlurDirectly", value / 50f, mWindow ) } } dragView = XposedHelpers.callMethod(dragObject, "getDragView") as View targetView = XposedHelpers.callMethod(dragView, "getContent") as ViewGroup valueAnimator.duration = 200 valueAnimator.start() hideBlurDrawable() isShortcutMenuLayerBlurred = true } }) XposedBridge.hookAllMethods( shortcutMenuLayerClass, "onDragStart", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (isShortcutMenuLayerBlurred) { if (targetView != null) { targetView!!.transitionAlpha = 0f } } } }) XposedBridge.hookAllMethods( shortcutMenuLayerClass, "onDragEnd", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (isShortcutMenuLayerBlurred) { val isLocked = XposedHelpers.callStaticMethod( utilitiesClass, "isScreenCellsLocked" ) as Boolean if (isLocked && dragView != null) { animate(dragView!!).scaleX(1f).scaleY(1f).setDuration(200).start() } } } }) XposedBridge.hookAllMethods(dragViewClass, "remove", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (isShortcutMenuLayerBlurred) { param.result = null } } }) XposedBridge.hookAllMethods( shortcutMenuClass, "reset", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (isShortcutMenuLayerBlurred) { isShortcutMenuLayerBlurred = false if (targetView != null) { targetView!!.transitionAlpha = 1f } val mLauncher = XposedHelpers.callStaticMethod(applicationClass, "getLauncher") val systemUiController = XposedHelpers.callMethod(mLauncher, "getSystemUiController") val mWindow = HookUtils.getValueByField(systemUiController, "mWindow") if (blurBackground) { XposedHelpers.callStaticMethod( blurUtilsClass, "fastBlurDirectly", 0f, mWindow ) } } } }) XposedBridge.hookAllMethods( shortcutMenuLayerClass, "hideShortcutMenu", object : XC_MethodHook() { @RequiresApi(Build.VERSION_CODES.S) override fun beforeHookedMethod(param: MethodHookParam) { if (isShortcutMenuLayerBlurred) { val editStateChangeReason = param.args[0] val shortcutMenuLayer = param.thisObject as FrameLayout val mLauncher = XposedHelpers.callStaticMethod(applicationClass, "getLauncher") val systemUiController = XposedHelpers.callMethod(mLauncher, "getSystemUiController") val mWindow = HookUtils.getValueByField(systemUiController, "mWindow") val targetBlurView = XposedHelpers.callMethod(mLauncher, "getScreen") as View val valueAnimator = ValueAnimator.ofInt(50, 0) val renderEffectArray = arrayOfNulls(51) for (index in 0..50) { renderEffectArray[index] = RenderEffect.createBlurEffect( (index + 1).toFloat(), (index + 1).toFloat(), Shader.TileMode.MIRROR ) } valueAnimator.addUpdateListener { animator -> val value = animator.animatedValue as Int targetBlurView.setRenderEffect(renderEffectArray[value]) // 修复始终模糊壁纸模糊丢失 if (blurBackground && !mPrefsMap.getBoolean("home_other_always_blur_launcher_wallpaper")) { XposedHelpers.callStaticMethod( blurUtilsClass, "fastBlurDirectly", value / 50f, mWindow ) } } valueAnimator.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { shortcutMenuLayer.background = null showBlurDrawable() targetView!!.transitionAlpha = 1f targetBlurView.setRenderEffect(null) isShortcutMenuLayerBlurred = false if (editStateChangeReason != null && editStateChangeReason.toString() != "drag_over_threshold") { XposedHelpers.callMethod(dragView, "remove") } } }) valueAnimator.duration = 200 valueAnimator.start() if (editStateChangeReason != null) { XposedLogUtils.logI(editStateChangeReason.toString()) } else { isShortcutMenuLayerBlurred = false XposedHelpers.callMethod(dragView, "remove") } } } }) XposedBridge.hookAllMethods( blurUtilsClass, "fastBlurDirectly", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { val blurRatio = param.args[0] as Float if (isShortcutMenuLayerBlurred && blurRatio == 0.0f) { param.result = null } } }) if (shortcutMenuBackgroundAlpha != 255) { XposedBridge.hookAllMethods( shortcutMenuClass, "setMenuBg", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isShortcutMenuLayerBlurred) { return } val mAppShortcutMenu: ViewGroup val mAppShortcutMenuBackground: GradientDrawable val mSystemShortcutMenu: ViewGroup val mSystemShortcutMenuBackground: GradientDrawable /* val mWidgetShortcutMenu: ViewGroup val mWidgetShortcutMenuBackground: GradientDrawable */ val mAppPersonaliseShortcutMenu: ViewGroup val mAppPersonaliseShortcutMenuBackground: GradientDrawable val mFolderShortcutMenu: ViewGroup val mFolderShortcutMenuBackground: GradientDrawable try { mAppShortcutMenu = param.thisObject.getObjectField("mAppShortcutMenu") as ViewGroup mAppShortcutMenuBackground = mAppShortcutMenu.background as GradientDrawable mAppShortcutMenuBackground.alpha = singleLayerAlpha for (index in 0..mAppShortcutMenu.childCount) { val child = mAppShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } } catch (e: Exception) { XposedLogUtils.logI("BlurWhenShowShortcutMenu get mAppShortcutMenu failed by: $e") } try { mSystemShortcutMenu = param.thisObject.getObjectField("mSystemShortcutMenu") as ViewGroup mSystemShortcutMenuBackground = mSystemShortcutMenu.background as GradientDrawable mSystemShortcutMenuBackground.alpha = singleLayerAlpha for (index in 0..mSystemShortcutMenu.childCount) { val child = mSystemShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } } catch (e: Exception) { XposedLogUtils.logI("BlurWhenShowShortcutMenu get mSystemShortcutMenu failed by: $e") } try { mAppPersonaliseShortcutMenu = param.thisObject.getObjectField("mAppPersonaliseShortcutMenu") as ViewGroup mAppPersonaliseShortcutMenuBackground = mAppPersonaliseShortcutMenu.background as GradientDrawable mAppPersonaliseShortcutMenuBackground.alpha = singleLayerAlpha for (index in 0..mAppPersonaliseShortcutMenu.childCount) { val child = mAppPersonaliseShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } } catch (e: Exception) { XposedLogUtils.logI("BlurWhenShowShortcutMenu get mAppPersonaliseShortcutMenu failed by: $e") } try { mFolderShortcutMenu = param.thisObject.getObjectField("mFolderShortcutMenu") as ViewGroup mFolderShortcutMenuBackground = mFolderShortcutMenu.background as GradientDrawable mFolderShortcutMenuBackground.alpha = singleLayerAlpha for (index in 0..mFolderShortcutMenu.childCount) { val child = mFolderShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } } catch (e: Exception) { XposedLogUtils.logI("BlurWhenShowShortcutMenu get mFolderShortcutMenu failed by: $e") } /*try { mWidgetShortcutMenu = param.thisObject.getObjectField("mWidgetShortcutMenu") as ViewGroup mWidgetShortcutMenuBackground = mWidgetShortcutMenu.background as GradientDrawable mWidgetShortcutMenuBackground.alpha = singleLayerAlpha for (index in 0..mWidgetShortcutMenu.childCount) { val child = mWidgetShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } } catch (e: Exception) { XposedBridge.log("Cemiuiler: BlurWhenShowShortcutMenu get mWidgetShortcutMenu failed by: $e") }*/ } }) XposedBridge.hookAllMethods( shortcutMenuClass, "addArrow", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isShortcutMenuLayerBlurred) { return } val mArrow = HookUtils.getValueByField( param.thisObject, "mArrow" ) as View val mArrowBackground = mArrow.background as ShapeDrawable mArrowBackground.alpha = shortcutMenuBackgroundAlpha } }) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/DisableHideGoogle.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import android.content.ComponentName import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers import miui.os.Build @Suppress("UNCHECKED_CAST") object DisableHideGoogle : BaseHook() { override fun init() { if (Build.IS_INTERNATIONAL_BUILD) return XposedHelpers.findAndHookConstructor( "com.miui.home.launcher.AppFilter", lpparam.classLoader, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val skippedItem = XposedHelpers.getObjectField( param.thisObject, "mSkippedItems" ) as HashSet skippedItem.removeIf { it.packageName == "com.google.android.googlequicksearchbox" || it.packageName == "com.google.android.gms" } } } ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/FixAndroidRS.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedHelpers object FixAndroidRS : BaseHook() { override fun init() { val globalSearchUtilClass = "com.miui.home.launcher.GlobalSearchUtil" XposedHelpers.findAndHookMethod(globalSearchUtilClass, lpparam.classLoader, "isSupportPullDownSearch", object : XC_MethodReplacement() { override fun replaceHookedMethod(param: MethodHookParam?): Any { return false } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/FreeformShortcutMenu.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.other; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static de.robv.android.xposed.XC_MethodReplacement.returnConstant; import static de.robv.android.xposed.XposedHelpers.callMethod; import android.annotation.SuppressLint; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; import android.view.View; import androidx.core.content.ContextCompat; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.util.ArrayList; import java.util.List; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; public class FreeformShortcutMenu extends BaseHook { Class mActivity; Class mViewDarkModeHelper; Class mSystemShortcutMenu; Class mSystemShortcutMenuItem; Class mAppShortcutMenu; Class mShortcutMenuItem; Class mAppDetailsShortcutMenuItem; Class mActivityUtilsCompat; Class mRecentsAndFSGestureUtils; Context mContext; XC_MethodHook.Unhook mShortCutMenuItemHook; @Override public void init() { if (isPad()) { hookAllMethods("com.miui.home.launcher.shortcuts.SystemShortcutMenuItem$MultipleSmallWindowShortcutMenuItem", "isValid", new MethodHook() { @Override protected void before(MethodHookParam param) { returnConstant(true); } }); hookAllMethods("com.miui.home.launcher.shortcuts.SystemShortcutMenuItem$SmallWindowShortcutMenuItem", "isValid", new MethodHook() { @Override protected void before(MethodHookParam param) { returnConstant(true); } }); return; } mActivity = Activity.class; mViewDarkModeHelper = findClassIfExists("com.miui.home.launcher.util.ViewDarkModeHelper"); mSystemShortcutMenu = findClassIfExists("com.miui.home.launcher.shortcuts.SystemShortcutMenu"); mSystemShortcutMenuItem = findClassIfExists("com.miui.home.launcher.shortcuts.SystemShortcutMenuItem"); mAppShortcutMenu = findClassIfExists("com.miui.home.launcher.shortcuts.AppShortcutMenu"); mShortcutMenuItem = findClassIfExists("com.miui.home.launcher.shortcuts.ShortcutMenuItem"); mAppDetailsShortcutMenuItem = findClassIfExists("com.miui.home.launcher.shortcuts.SystemShortcutMenuItem$AppDetailsShortcutMenuItem"); mActivityUtilsCompat = findClassIfExists("com.miui.launcher.utils.ActivityUtilsCompat"); mRecentsAndFSGestureUtils = findClassIfExists("com.miui.home.launcher.RecentsAndFSGestureUtils"); try { hookAllMethods(mViewDarkModeHelper, "onConfigurationChanged", new MethodHook() { @Override protected void after(MethodHookParam param) { XposedHelpers.callStaticMethod(mSystemShortcutMenuItem, "createAllSystemShortcutMenuItems"); } }); hookAllMethods(mShortcutMenuItem, "getShortTitle", new MethodHook() { @Override protected void after(MethodHookParam param) { if (param.getResult().equals("应用信息")) { param.setResult("信息"); } if (param.getResult().equals("新建窗口")) { param.setResult("多开"); } } }); hookAllMethods(mActivity, "onCreate", new MethodHook() { @Override protected void after(MethodHookParam param) { mContext = (Context) param.thisObject; } }); findAndHookMethod(mAppDetailsShortcutMenuItem, "getOnClickListener", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Resources modRes = Helpers.getModuleRes(mContext); Object obj = param.thisObject; CharSequence mShortTitle = (CharSequence) callMethod(obj, "getShortTitle"); if (mShortTitle.equals(modRes.getString(R.string.share_center))) { XposedHelpers.callStaticMethod(mRecentsAndFSGestureUtils, "startWorld", mContext); } else if (mShortTitle.equals(modRes.getString(R.string.floating_window))) { param.setResult(getFreeformOnClickListener(obj, false)); } else if (mShortTitle.equals(modRes.getString(R.string.new_task))) { param.setResult(getFreeformOnClickListener(obj, true)); } } }); hookAllMethods(mSystemShortcutMenu, "getMaxShortcutItemCount", new MethodHook() { @Override protected void after(MethodHookParam param) { param.setResult(6); } }); hookAllMethods(mAppShortcutMenu, "getMaxShortcutItemCount", new MethodHook() { @Override protected void after(MethodHookParam param) { param.setResult(6); } }); hookAllMethods(mSystemShortcutMenuItem, "createAllSystemShortcutMenuItems", new MethodHook() { @SuppressLint("DiscouragedApi") @Override protected void after(MethodHookParam param) throws Throwable { Resources modRes = Helpers.getModuleRes(mContext); List mAllSystemShortcutMenuItems = (List) XposedHelpers.getStaticObjectField(mSystemShortcutMenuItem, "sAllSystemShortcutMenuItems"); Object mSmallWindowInstance = XposedHelpers.newInstance(mAppDetailsShortcutMenuItem); Object mNewTasksInstance = XposedHelpers.newInstance(mAppDetailsShortcutMenuItem); if (mPrefsMap.getBoolean("home_other_freeform_shortcut_menu")) { callMethod(mSmallWindowInstance, "setShortTitle", modRes.getString(R.string.floating_window)); callMethod(mSmallWindowInstance, "setIconDrawable", ContextCompat.getDrawable(mContext, mContext.getResources().getIdentifier("ic_task_small_window", "drawable", mContext.getPackageName()))); } if (mPrefsMap.getBoolean("home_other_tasks_shortcut_menu")) { callMethod(mNewTasksInstance, "setShortTitle", modRes.getString(R.string.new_task)); callMethod(mNewTasksInstance, "setIconDrawable", ContextCompat.getDrawable(mContext, mContext.getResources().getIdentifier("ic_task_add_pair", "drawable", mContext.getPackageName()))); } ArrayList sAllSystemShortcutMenuItems = new ArrayList(); if (mPrefsMap.getBoolean("home_other_freeform_shortcut_menu")) sAllSystemShortcutMenuItems.add(mSmallWindowInstance); if (mPrefsMap.getBoolean("home_other_tasks_shortcut_menu")) sAllSystemShortcutMenuItems.add(mNewTasksInstance); sAllSystemShortcutMenuItems.addAll(mAllSystemShortcutMenuItems); XposedHelpers.setStaticObjectField(mSystemShortcutMenuItem, "sAllSystemShortcutMenuItems", sAllSystemShortcutMenuItems); } }); } catch (Throwable th) { XposedLogUtils.logW(TAG, "FreeformShortcutMenu", th); } } private View.OnClickListener getFreeformOnClickListener(Object obj, boolean isNewTaskOnClick) { return view -> { Intent intent = new Intent(); Context mContext1 = view.getContext(); ComponentName mComponentName = (ComponentName) callMethod(obj, "getComponentName", new Object[0]); intent.setAction("android.intent.action.MAIN"); intent.addCategory("android.intent.category.DEFAULT"); intent.setComponent(mComponentName); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (isNewTaskOnClick) { intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK); } Object makeFreeformActivityOptions = XposedHelpers.callStaticMethod(mActivityUtilsCompat, "makeFreeformActivityOptions", mContext1, mComponentName.getPackageName()); if (makeFreeformActivityOptions != null) { mContext1.startActivity(intent, (Bundle) callMethod(makeFreeformActivityOptions, "toBundle", new Object[0])); } }; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/HomeMode.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.other; import com.sevtinge.cemiuiler.module.base.BaseHook; public class HomeMode extends BaseHook { Class mDeviceConfig; @Override public void init() { mDeviceConfig = findClassIfExists("com.miui.home.launcher.DeviceConfig"); findAndHookMethod(mDeviceConfig, "isDarkMode", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { int mHomeMode = mPrefsMap.getStringAsInt("home_other_home_mode", 0); boolean isHomeMode = !(mHomeMode == 2); param.setResult(isHomeMode); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/InfiniteScroll.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.other; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class InfiniteScroll extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.launcher.ScreenView", "getSnapToScreenIndex", int.class, int.class, int.class, new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { if (param.args[0] != param.getResult()) return; int screenCount = (int) XposedHelpers.callMethod(param.thisObject, "getScreenCount"); if ((int) param.args[2] == -1 && (int) param.args[0] == 0) param.setResult(screenCount); else if ((int) param.args[2] == 1 && (int) param.args[0] == screenCount - 1) param.setResult(0); } }); findAndHookMethod("com.miui.home.launcher.ScreenView", "getSnapUnitIndex", int.class, new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { int index = (int) param.getResult(); int mCurrentScreenIndex = XposedHelpers.getIntField(param.thisObject, lpparam.packageName.equals("com.miui.home") ? "mCurrentScreenIndex" : "mCurrentScreen"); if (mCurrentScreenIndex != index) return; int screenCount = (int) XposedHelpers.callMethod(param.thisObject, "getScreenCount"); if (index == 0) { param.setResult(screenCount); } else if (index == screenCount - 1) { param.setResult(0); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/OverlapMode.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class OverlapMode : BaseHook() { override fun init() { // Fold2 样式负一屏 loadClass("com.miui.home.launcher.overlay.assistant.AssistantDeviceAdapter").methodFinder() .first { name == "inOverlapMode" }.createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/ShortcutBackgroundBlur.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator import android.app.Activity import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.RenderEffect import android.graphics.Shader import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.graphics.drawable.ShapeDrawable import android.os.Build import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import androidx.annotation.RequiresApi import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.* import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import kotlin.math.sqrt object ShortcutBackgroundBlur : BaseHook() { @RequiresApi(Build.VERSION_CODES.S) override fun init() { // if (!mPrefsMap.getBoolean("home_shortcut_blur")) return // From WINI with MIT val shortcutMenuBackgroundAlpha = mPrefsMap.getInt("home_other_shortcut_background_blur_custom", 200) val shortcutMenuLayerClass = findClassIfExists("com.miui.home.launcher.ShortcutMenuLayer") val shortcutMenuClass = findClassIfExists("com.miui.home.launcher.shortcuts.ShortcutMenu") val blurUtilsClass = findClassIfExists("com.miui.home.launcher.common.BlurUtils") val applicationClass = findClassIfExists("com.miui.home.launcher.Application") val utilitiesClass = findClassIfExists("com.miui.home.launcher.common.Utilities") val launcherStateClass = findClassIfExists("com.miui.home.launcher.LauncherState") /* 两层视图alpha计算公式:2x-x^2=y x为单层视图alpha 0完全透明 1完全不透明 y为双层混合后的透明度 x与y在图层透明度这种情况下永远为正值 将改公式转换为x=f(y):x=1-√(1-y) */ val singleLayerAlpha = ((1.0 - sqrt(1.0 - (shortcutMenuBackgroundAlpha / 255.0))) * 255.0).toInt() XposedLogUtils.logI("" + shortcutMenuBackgroundAlpha) XposedLogUtils.logI("" + singleLayerAlpha) val mBlurIconAppName = arrayOf("锁屏", "手电筒", "数据", "飞行模式", "蓝牙", "WLAN 热点") val allBlurredDrawable: MutableList = ArrayList() fun showBlurDrawable() { allBlurredDrawable.forEach { drawable -> XposedHelpers.callMethod(drawable, "setVisible", true, false) } } fun hideBlurDrawable() { allBlurredDrawable.forEach { drawable -> XposedHelpers.callMethod(drawable, "setVisible", false, false) } } var isShortcutMenuLayerBlurred = false var dragLayer: ViewGroup? = null var targetView: View? = null var dragLayerBackground: Drawable? = null shortcutMenuLayerClass.hookBeforeAllMethods("showShortcutMenu") { hideBlurDrawable() val dragObject = it.args[0] val dragViewInfo = dragObject.callMethod("getDragInfo") val iconIsInFolder = dragViewInfo?.callMethod("isInFolder") as Boolean if (iconIsInFolder) return@hookBeforeAllMethods // 文件夹内不模糊 val iconIsApplication = dragViewInfo.callMethod("isApplicatoin") as Boolean val iconTitle = dragViewInfo.callMethod("getTitle") as String if (!iconIsApplication && !mBlurIconAppName.contains(iconTitle)) return@hookBeforeAllMethods val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity val launcherStatusField = launcherStateClass.getDeclaredField("ALL_APPS") launcherStatusField.isAccessible = true val allAppsStatus = launcherStatusField.get(null) val stateManager = mLauncher.callMethod("getStateManager") val currentState = stateManager?.callMethod("getState") if (currentState == allAppsStatus) return@hookBeforeAllMethods val targetBlurView = mLauncher.callMethod("getScreen") as View val renderEffectArray = arrayOfNulls(51) for (index in 0..50) { renderEffectArray[index] = RenderEffect.createBlurEffect((index + 1).toFloat(), (index + 1).toFloat(), Shader.TileMode.MIRROR) } val valueAnimator = ValueAnimator.ofInt(0, 50) valueAnimator.addUpdateListener { animator -> val value = animator.animatedValue as Int if (!mPrefsMap.getBoolean("home_blur_wallpaper")) { blurUtilsClass.callStaticMethod("fastBlurDirectly", value / 50f, mLauncher.window) } targetBlurView.setRenderEffect(renderEffectArray[value]) } val dragView = dragObject.callMethod("getDragView") as View targetView = dragView.callMethod("getContent") as View dragLayer = targetBlurView.parent as ViewGroup valueAnimator.duration = 200 valueAnimator.start() isShortcutMenuLayerBlurred = true } shortcutMenuLayerClass.hookBeforeAllMethods("onDragStart") { if (isShortcutMenuLayerBlurred) { val dragObject = it.args[1] val dragView = dragObject.callMethod("getDragView") as View val dragViewParent = dragView.parent as View val bitmap = Bitmap.createBitmap(dragLayer!!.width, dragLayer!!.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) val originalScale = dragView.scaleX dragView.scaleX = 1f dragView.scaleY = 1f dragViewParent.draw(canvas) dragView.scaleX = originalScale dragView.scaleY = originalScale dragLayerBackground = BitmapDrawable(dragLayer!!.context.resources, bitmap) targetView?.alpha = 0f } } shortcutMenuLayerClass.hookBeforeAllMethods("onDragEnd") { if (isShortcutMenuLayerBlurred) { val isLocked = utilitiesClass.callStaticMethod("isScreenCellsLocked") as Boolean if (isLocked) { dragLayer?.background = dragLayerBackground } else { val valueAnimator = ValueAnimator.ofFloat(0f, 1f) valueAnimator.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { dragLayer?.background = dragLayerBackground } }) valueAnimator.duration = 200 valueAnimator.start() } } } shortcutMenuClass.hookBeforeAllMethods("reset") { if (isShortcutMenuLayerBlurred) { isShortcutMenuLayerBlurred = false targetView!!.alpha = 1f val mLauncher = applicationClass.callStaticMethod("getLauncher") val systemUiController = mLauncher?.callMethod("getSystemUiController") val mWindow = systemUiController?.getObjectField("mWindow") blurUtilsClass.callStaticMethod("fastBlurDirectly", 0f, mWindow) } } shortcutMenuLayerClass.hookBeforeAllMethods("hideShortcutMenu") { if (isShortcutMenuLayerBlurred) { val shortcutMenuLayer = it.thisObject as FrameLayout val mLauncher = XposedHelpers.callStaticMethod(applicationClass, "getLauncher") val systemUiController = XposedHelpers.callMethod(mLauncher, "getSystemUiController") val mWindow = systemUiController.getObjectField("mWindow") val targetBlurView = mLauncher.callMethod("getScreen") as View val valueAnimator = ValueAnimator.ofInt(50, 0) val renderEffectArray = arrayOfNulls(51) for (index in 0..50) { renderEffectArray[index] = RenderEffect.createBlurEffect( (index + 1).toFloat(), (index + 1).toFloat(), Shader.TileMode.MIRROR ) } valueAnimator.addUpdateListener { animator -> val value = animator.animatedValue as Int targetBlurView.setRenderEffect(renderEffectArray[value]) if (!mPrefsMap.getBoolean("home_blur_wallpaper")) { blurUtilsClass.callStaticMethod("fastBlurDirectly", value / 50f, mWindow) } } valueAnimator.addListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { shortcutMenuLayer.background = null showBlurDrawable() targetView!!.alpha = 1f targetBlurView.setRenderEffect(null) dragLayer?.background = null } }) valueAnimator.duration = 200 valueAnimator.start() } isShortcutMenuLayerBlurred = false } blurUtilsClass.hookBeforeAllMethods("fastBlurDirectly") { val blurRatio = it.args[0] as Float if (isShortcutMenuLayerBlurred && blurRatio == 0.0f) { it.result = null } } if (shortcutMenuBackgroundAlpha != 255) { XposedBridge.hookAllMethods( shortcutMenuClass, "setMenuBg", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isShortcutMenuLayerBlurred) { return } val mAppShortcutMenu: ViewGroup val mAppShortcutMenuBackground: GradientDrawable val mSystemShortcutMenu: ViewGroup val mSystemShortcutMenuBackground: GradientDrawable val mWidgetShortcutMenu: ViewGroup val mWidgetShortcutMenuBackground: GradientDrawable try { mAppShortcutMenu = param.thisObject.getObjectField("mAppShortcutMenu") as ViewGroup mAppShortcutMenuBackground = mAppShortcutMenu.background as GradientDrawable mAppShortcutMenuBackground.alpha = singleLayerAlpha for (index in 0..mAppShortcutMenu.childCount) { val child = mAppShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } } catch (_: Exception) { } try { mSystemShortcutMenu = param.thisObject.getObjectField("mSystemShortcutMenu") as ViewGroup mSystemShortcutMenuBackground = mSystemShortcutMenu.background as GradientDrawable mSystemShortcutMenuBackground.alpha = singleLayerAlpha for (index in 0..mSystemShortcutMenu.childCount) { val child = mSystemShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } } catch (_: Exception) { } try { mWidgetShortcutMenu = param.thisObject.getObjectField("mWidgetShortcutMenu") as ViewGroup mWidgetShortcutMenuBackground = mWidgetShortcutMenu.background as GradientDrawable mWidgetShortcutMenuBackground.alpha = singleLayerAlpha for (index in 0..mWidgetShortcutMenu.childCount) { val child = mWidgetShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } } catch (_: Exception) { } } }) XposedBridge.hookAllMethods(shortcutMenuClass, "addArrow", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isShortcutMenuLayerBlurred) { return } val mArrow = HookUtils.getValueByField( param.thisObject, "mArrow" ) as View val mArrowBackground = mArrow.background as ShapeDrawable mArrowBackground.alpha = shortcutMenuBackgroundAlpha } } ) } /* if (shortcutMenuBackgroundAlpha != 255) { log("1") shortcutMenuClass.hookBeforeAllMethods("setMenuBg") { log("3") if (!isShortcutMenuLayerBlurred) { log("2") return@hookBeforeAllMethods } val mAppShortcutMenu = it.thisObject.getObjectField("mAppShortcutMenu") as ViewGroup val mAppShortcutMenuBackground = mAppShortcutMenu.background as GradientDrawable mAppShortcutMenuBackground.alpha = singleLayerAlpha val mSystemShortcutMenu = it.thisObject.getObjectField("mSystemShortcutMenu") as ViewGroup val mSystemShortcutMenuBackground = mSystemShortcutMenu.background as GradientDrawable mSystemShortcutMenuBackground.alpha = singleLayerAlpha for (index in 0..mAppShortcutMenu.childCount) { val child = mAppShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } for (index in 0..mSystemShortcutMenu.childCount) { val child = mSystemShortcutMenu.getChildAt(index) if (child != null && child.background != null) { if (child.background is Drawable) { val childBackground = child.background as Drawable childBackground.alpha = singleLayerAlpha } } } } shortcutMenuClass.hookAfterAllMethods("addArrow") { log("4") if (!isShortcutMenuLayerBlurred) { log("5") return@hookAfterAllMethods } val mArrow = it.thisObject.getObjectField("mArrow") as View val mArrowBackground = mArrow.background as ShapeDrawable mArrowBackground.alpha = shortcutMenuBackgroundAlpha } } */ blurUtilsClass.hookAfterAllMethods("fastBlurWhenEnterRecents") { val launcher = it.args[0] if (launcher != null) { XposedHelpers.callMethod(launcher, "hideShortcutMenuWithoutAnim") } hideBlurDrawable() } blurUtilsClass.hookAfterAllMethods("fastBlurWhenExitRecents") { showBlurDrawable() } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/ShortcutItemCount.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod object ShortcutItemCount : BaseHook() { override fun init() { val mAppShortcutMenuClass = loadClass("com.miui.home.launcher.shortcuts.AppShortcutMenu") mAppShortcutMenuClass.methodFinder().first { name == "getMaxCountInCurrentOrientation" }.createHook { after { it.result = 20 } } mAppShortcutMenuClass.methodFinder().first { name == "getMaxShortcutItemCount" }.createHook { after { it.result = 20 } } mAppShortcutMenuClass.methodFinder().first { name == "getMaxVisualHeight" }.createHook { after { it.result = it.thisObject.callMethod("getItemHeight") } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/other/ShowAllHideApp.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.other import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object ShowAllHideApp : BaseHook() { override fun init() { dexKitBridge.findClass { matcher { addUsingStringsEquals("appInfo.packageName", "activityInfo") } }.forEach { it.getInstance(EzXHelper.classLoader).methodFinder().first { name == "isHideAppValid" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/AlwaysShowCleanUp.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.IS_TABLET import com.sevtinge.cemiuiler.utils.api.isPad object AlwaysShowCleanUp: BaseHook() { override fun init() { loadClass( when (IS_TABLET) { false -> "com.miui.home.recents.views.RecentsContainer" true -> "com.miui.home.recents.views.RecentsDecorations" } ).methodFinder().filterByName("updateClearContainerVisible") .first().createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/BlurLevel.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.app.Activity import android.view.MotionEvent import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.ObjectHelper.Companion.objectHelper import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.isPad import com.sevtinge.cemiuiler.utils.callStaticMethod import com.sevtinge.cemiuiler.utils.hookAfterAllMethods import com.sevtinge.cemiuiler.utils.hookBeforeMethod object BlurLevel : BaseHook() { private val blurLevel by lazy { mPrefsMap.getStringAsInt("home_recent_blur_level", 6) } override fun init() { val mBlurClass = loadClass("com.miui.home.launcher.common.BlurUtils") mBlurClass.methodFinder().first { name == "getBlurType" }.createHook { before { when (blurLevel) { 5 -> returnConstant(2) 0 -> returnConstant(2) 2 -> returnConstant(1) 3 -> returnConstant(0) 4 -> returnConstant(0) } } } when (blurLevel) { 4 -> { mBlurClass.methodFinder().first { name == "isUseCompleteBlurOnDev" }.createHook { returnConstant(false) } "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("isUseSimpleAnim") { it.result = true } } 5 -> { val blurClass = findClassIfExists("com.miui.home.launcher.common.BlurUtils") val navStubViewClass = findClassIfExists("com.miui.home.recents.NavStubView") val applicationClass = findClassIfExists("com.miui.home.launcher.Application") navStubViewClass.hookBeforeMethod("onPointerEvent", MotionEvent::class.java) { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity val motionEvent = it.args[0] as MotionEvent val action = motionEvent.action if (action == 2) Thread.currentThread().priority = 10 if (it.thisObject.objectHelper().getObjectOrNull("mWindowMode") == 2 && action == 2) { blurClass.callStaticMethod("fastBlurDirectly", 1.0f, mLauncher.window) } } "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("isUseSimpleAnim") { it.result = false } if (isPad()) { navStubViewClass.hookAfterAllMethods("onTouchEvent") { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity blurClass.callStaticMethod("fastBlur", 1.0f, mLauncher.window, true, 500L) } } /* navStubViewClass.hookBeforeMethod("appTouchResolution", MotionEvent::class.java) { val mLauncher = applicationClass.callStaticMethod("getLauncher") as Activity blurClass.callStaticMethod("fastBlurDirectly", 1.0f, mLauncher.window) }*/ } else -> { "com.miui.home.launcher.common.DeviceLevelUtils".hookBeforeMethod("isUseSimpleAnim") { it.result = false } mBlurClass.methodFinder().first { name == "isUseCompleteBlurOnDev" }.createHook { before { when (blurLevel) { 1 -> returnConstant(true) } } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/CardTextColor.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.widget.TextView import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod object CardTextColor : BaseHook() { override fun init() { val recentTextColor = mPrefsMap.getInt("home_recent_text_color", -1) if (recentTextColor != -1) { val taskViewHeaderClass = "com.miui.home.recents.views.TaskViewHeader".findClass() taskViewHeaderClass.hookAfterMethod( "onFinishInflate" ) { val mTitle = it.thisObject.getObjectField("mTitleView") as TextView mTitle.setTextColor(recentTextColor) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/CardTextSize.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.util.TypedValue import android.view.View import android.widget.TextView import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod object CardTextSize : BaseHook() { override fun init() { val recentTextSize = mPrefsMap.getInt("home_recent_text_size", -1) if (recentTextSize != -1) { val taskViewHeaderClass = "com.miui.home.recents.views.TaskViewHeader".findClass() taskViewHeaderClass.hookAfterMethod( "onFinishInflate" ) { val mTitle = it.thisObject.getObjectField("mTitleView") as TextView mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, recentTextSize.toFloat()) if (recentTextSize == 0) mTitle.visibility = View.GONE } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/DisableRecentViewWallpaperDarken.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.setObjectField object DisableRecentViewWallpaperDarken : BaseHook() { override fun init() { // if (!mPrefsMap.getBoolean("home_disable_darken")) return loadClass("com.miui.home.recents.DimLayer").methodFinder().first { name == "dim" && parameterCount == 3 }.createHook { before { it.args[0] = 0.0f it.thisObject.setObjectField("mCurrentAlpha", 0.0f) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/FreeformCardBackgroundColor.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.hookAfterAllConstructors import com.sevtinge.cemiuiler.utils.setIntField object FreeformCardBackgroundColor : BaseHook() { override fun init() { val appCardBgColor = mPrefsMap.getInt("home_recent_freeform_background_color", -1) if (appCardBgColor != -1) { "com.miui.home.recents.views.TaskViewThumbnail".findClass().hookAfterAllConstructors { it.thisObject.setIntField("mBgColorForSmallWindow", appCardBgColor) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/HideCleanUp.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.view.View import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod object HideCleanUp : BaseHook() { override fun init() { val recentsContainerClass = "com.miui.home.recents.views.RecentsContainer".findClass() if (mPrefsMap.getBoolean("home_recent_hide_clean_up")) { recentsContainerClass.hookAfterMethod( "onFinishInflate" ) { val mView = it.thisObject.getObjectField("mClearAnimView") as View mView.visibility = View.GONE } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/HideFreeform.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.view.View import android.widget.TextView import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod object HideFreeform : BaseHook() { override fun init() { val recentsContainerClass = "com.miui.home.recents.views.RecentsContainer".findClass() if (mPrefsMap.getBoolean("home_recent_hide_freeform")) { recentsContainerClass.hookAfterMethod( "onFinishInflate" ) { val mTitle = it.thisObject.getObjectField("mTxtSmallWindow") as TextView mTitle.visibility = View.GONE } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/HideStatusBarWhenEnterRecent.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object HideStatusBarWhenEnterRecent : BaseHook() { override fun init() { val mDeviceLevelClass = loadClass("com.miui.home.launcher.common.DeviceLevelUtils") if (mPrefsMap.getBoolean("home_recent_hide_status_bar_in_task_view")) { mDeviceLevelClass.methodFinder().first { name == "isHideStatusBarWhenEnterRecents" }.createHook { returnConstant(true) } loadClass("com.miui.home.launcher.DeviceConfig").methodFinder().first { name == "keepStatusBarShowingForBetterPerformance" }.createHook { returnConstant(false) } } else { mDeviceLevelClass.methodFinder().first { name == "isHideStatusBarWhenEnterRecents" }.createHook { returnConstant(false) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/MemInfoShow.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object MemInfoShow : BaseHook() { override fun init() { loadClass("com.miui.home.recents.views.RecentsDecorations").methodFinder().first { name == "canTxtMemInfoShow" }.createHook { before { param -> param.result = true } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/RealMemory.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.annotation.SuppressLint import android.app.ActivityManager import android.content.Context import android.text.format.Formatter import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.ConstructorFinder.`-Static`.constructorFinder import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.IS_TABLET import com.sevtinge.cemiuiler.utils.api.isPad import com.sevtinge.cemiuiler.utils.getObjectField // @SuppressLint("StaticFieldLeak") object RealMemory : BaseHook() { @SuppressLint("DiscouragedApi") override fun init() { lateinit var context: Context var memoryInfo1StringId: Int? = null var memoryInfo2StringId: Int? = null fun Any.formatSize(): String = Formatter.formatFileSize(context, this as Long) val recentContainerClass = loadClass( when (IS_TABLET) { false -> "com.miui.home.recents.views.RecentsContainer" true -> "com.miui.home.recents.views.RecentsDecorations" } ) recentContainerClass.declaredConstructors.constructorFinder() .filterByParamCount(2) .first().createHook { after { context = it.args[0] as Context memoryInfo1StringId = context.resources.getIdentifier( "status_bar_recent_memory_info1", "string", "com.miui.home" ) memoryInfo2StringId = context.resources.getIdentifier( "status_bar_recent_memory_info2", "string", "com.miui.home" ) } } recentContainerClass.methodFinder() .filterByName("refreshMemoryInfo") .first().createHook { before { it.result = null val memoryInfo = ActivityManager.MemoryInfo() val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager activityManager.getMemoryInfo(memoryInfo) val totalMem = memoryInfo.totalMem.formatSize() val availMem = memoryInfo.availMem.formatSize() (it.thisObject.getObjectField("mTxtMemoryInfo1") as TextView).text = context.getString(memoryInfo1StringId!!, availMem, totalMem) (it.thisObject.getObjectField("mTxtMemoryInfo2") as TextView).text = context.getString(memoryInfo2StringId!!, availMem, totalMem) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/RecentResource.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.app.Application import android.content.Context import android.content.res.Resources import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.EzXHelper.appContext import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.ResourcesHookData import com.sevtinge.cemiuiler.utils.ResourcesHookMap import com.sevtinge.cemiuiler.utils.devicesdk.dp2px import com.sevtinge.cemiuiler.utils.hookBeforeMethod import de.robv.android.xposed.XC_MethodHook object RecentResource : BaseHook() { private val hookMap = ResourcesHookMap() private fun hook(param: XC_MethodHook.MethodHookParam) { try { val resName = appContext.resources.getResourceEntryName(param.args[0] as Int) val resType = appContext.resources.getResourceTypeName(param.args[0] as Int) if (hookMap.isKeyExist(resName)) if (hookMap[resName]?.type == resType) { param.result = hookMap[resName]?.afterValue } } catch (ignore: Exception) { } } override fun init() { Application::class.java.hookBeforeMethod("attach", Context::class.java) { it -> EzXHelper.initHandleLoadPackage(lpparam) EzXHelper.setLogTag(TAG) EzXHelper.setToastTag(TAG) EzXHelper.initAppContext(it.args[0] as Context) Resources::class.java.hookBeforeMethod("getBoolean", Int::class.javaPrimitiveType) { hook(it) } Resources::class.java.hookBeforeMethod("getDimension", Int::class.javaPrimitiveType) { hook(it) } Resources::class.java.hookBeforeMethod("getDimensionPixelOffset", Int::class.javaPrimitiveType) { hook(it) } Resources::class.java.hookBeforeMethod("getDimensionPixelSize", Int::class.javaPrimitiveType) { hook(it) } Resources::class.java.hookBeforeMethod("getInteger", Int::class.javaPrimitiveType) { hook(it) } Resources::class.java.hookBeforeMethod("getText", Int::class.javaPrimitiveType) { hook(it) } val value = mPrefsMap.getInt("task_view_corners", -1).toFloat() val value1 = mPrefsMap.getInt("task_view_header_height", -1).toFloat() if (value != -1f && value != 20f) { hookMap["recents_task_view_rounded_corners_radius_min"] = ResourcesHookData("dimen", dp2px(value)) hookMap["recents_task_view_rounded_corners_radius_max"] = ResourcesHookData("dimen", dp2px(value)) } if (value1 != -1f && value != 40f) hookMap["recents_task_view_header_height"] = ResourcesHookData("dimen", dp2px(value1)) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/RecentText.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.widget.TextView import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod object RecentText : BaseHook() { override fun init() { val emptyViewText = mPrefsMap.getString("home_recent_text", "") if (emptyViewText != "") { "com.miui.home.recents.views.RecentsView".hookAfterMethod( "showEmptyView", Int::class.javaPrimitiveType ) { (it.thisObject.getObjectField("mEmptyView") as TextView).apply { this.text = emptyViewText } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/RemoveCardAnim.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.animation.ObjectAnimator import android.view.MotionEvent import android.view.View import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.callStaticMethod import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod import com.sevtinge.cemiuiler.utils.replaceMethod import com.sevtinge.cemiuiler.utils.setObjectField object RemoveCardAnim : BaseHook() { override fun init() { "com.miui.home.recents.views.SwipeHelperForRecents".hookAfterMethod("onTouchEvent", MotionEvent::class.java) { if (it.thisObject.getObjectField("mCurrView") != null) { val taskView2 = it.thisObject.getObjectField("mCurrView") as View taskView2.alpha = 1f taskView2.scaleX = 1f taskView2.scaleY = 1f } } "com.miui.home.recents.TaskStackViewLayoutStyleHorizontal".replaceMethod( "createScaleDismissAnimation", View::class.java, Float::class.java ) { val view = it.args[0] as View val getScreenHeight = findClass("com.miui.home.launcher.DeviceConfig").callStaticMethod("getScreenHeight") as Int val ofFloat = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, view.translationY, -getScreenHeight * 1.1484375f) ofFloat.duration = 200 return@replaceMethod ofFloat } "com.miui.home.recents.views.VerticalSwipe".hookAfterMethod("calculate", Float::class.java) { val f = it.args[0] as Float val asScreenHeightWhenDismiss = "com.miui.home.recents.views.VerticalSwipe".findClass() .callStaticMethod("getAsScreenHeightWhenDismiss") as Int val f2 = f / asScreenHeightWhenDismiss val mTaskViewHeight = it.thisObject.getObjectField("mTaskViewHeight") as Float val mCurScale = it.thisObject.getObjectField("mCurScale") as Float val f3: Float = mTaskViewHeight * mCurScale val i = if (f2 > 0.0f) 1 else if (f2 == 0.0f) 0 else -1 val afterFrictionValue: Float = it.thisObject.callMethod("afterFrictionValue", f, asScreenHeightWhenDismiss) as Float if (i < 0) it.thisObject.setObjectField( "mCurTransY", (mTaskViewHeight / 2.0f + afterFrictionValue * 2) - (f3 / 2.0f) ) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/RemoveIcon.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.view.View import android.widget.ImageView import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod object RemoveIcon : BaseHook() { override fun init() { if (mPrefsMap.getBoolean("home_recent_remove_icon")) { "com.miui.home.recents.views.TaskViewHeader".hookAfterMethod( "onFinishInflate" ) { val mImage = it.thisObject.getObjectField("mIconView") as ImageView mImage.visibility = View.GONE } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/TaskViewHorizontal.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.graphics.RectF import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.callStaticMethod import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.hookAfterMethod object TaskViewHorizontal : BaseHook() { override fun init() { val value1 = mPrefsMap.getInt("task_view_horizontal1", 100).toFloat() / 100 val value2 = mPrefsMap.getInt("task_view_horizontal2", 100).toFloat() / 100 if (value1 == 1f && value2 == 1f) return "com.miui.home.recents.views.TaskStackViewsAlgorithmHorizontal".hookAfterMethod( "scaleTaskView", RectF::class.java, ) { "com.miui.home.recents.util.Utilities".findClass().callStaticMethod( "scaleRectAboutCenter", it.args[0], if (it.thisObject.callMethod("isLandscapeVisually") as Boolean) value2 else value1 ) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/recent/TaskViewVertical.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.recent import android.graphics.RectF import com.github.kyuubiran.ezxhelper.EzXHelper.appContext import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callStaticMethod import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.replaceMethod object TaskViewVertical : BaseHook() { override fun init() { val value = mPrefsMap.getInt("home_recent_vertical_task_view_card_size", 100).toFloat() / 100 if (value == -1f || value == 1f) return "com.miui.home.recents.views.TaskStackViewsAlgorithmVertical".replaceMethod( "scaleTaskView", RectF::class.java ) { "com.miui.home.recents.util.Utilities".findClass().callStaticMethod( "scaleRectAboutCenter", it.args[0], value * "com.miui.home.recents.util.Utilities".findClass() .callStaticMethod("getTaskViewScale", appContext) as Float ) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/AnimParamCustom.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import static de.robv.android.xposed.XposedHelpers.callMethod; import com.github.kyuubiran.ezxhelper.ClassUtils; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class AnimParamCustom extends BaseHook { @Override public void init() { hookAllMethods("com.miui.home.recents.util.RectFSpringAnim", "setAnimParamByType", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws NoSuchFieldException, ClassNotFoundException { Class clazzRectFSpringAnim = ClassUtils.loadClass("com.miui.home.recents.util.RectFSpringAnim", null); Object RECT_CENTERX = ClassUtils.getStaticObjectOrNull(clazzRectFSpringAnim, "RECT_CENTERX"); Object RECT_CENTERY = ClassUtils.getStaticObjectOrNull(clazzRectFSpringAnim, "RECT_CENTERY"); Object RECT_WIDTH = ClassUtils.getStaticObjectOrNull(clazzRectFSpringAnim, "RECT_WIDTH"); Object RECT_RATIO = ClassUtils.getStaticObjectOrNull(clazzRectFSpringAnim, "RECT_RATIO"); Object RADIUS = ClassUtils.getStaticObjectOrNull(clazzRectFSpringAnim, "RADIUS"); Object ALPHA = ClassUtils.getStaticObjectOrNull(clazzRectFSpringAnim, "ALPHA"); Enum animType = (Enum) param.args[0]; switch (animType.name()) { case "BREAK_OPEN" -> {// 1 callMethod(param.thisObject, "setAnimParam", RECT_CENTERX, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERX_1", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERX_1", 135) / 1000));// 0.99 0.135 callMethod(param.thisObject, "setAnimParam", RECT_CENTERY, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERY_1", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERY_1", 135) / 1000));// 0.99 0.135 callMethod(param.thisObject, "setAnimParam", RECT_WIDTH, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_WIDTH_1", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_WIDTH_1", 135) / 1000));// 0.99 0.135 callMethod(param.thisObject, "setAnimParam", RECT_RATIO, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_RATIO_1", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_RATIO_1", 135) / 1000));// 0.99 0.135 callMethod(param.thisObject, "setAnimParam", RADIUS, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RADIUS_1", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RADIUS_1", 135) / 1000));// 0.99 0.135 callMethod(param.thisObject, "setAnimParam", ALPHA, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_ALPHA_1", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_ALPHA_1", 135) / 1000));// 0.99 0.135 } case "OPEN_FROM_HOME" -> {// 2 callMethod(param.thisObject, "setAnimParam", RECT_CENTERX, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERX_2", 960) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERX_2", 300) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_CENTERY, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERY_2", 960) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERY_2", 300) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_WIDTH, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_WIDTH_2", 960) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_WIDTH_2", 410) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_RATIO, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_RATIO_2", 960) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_RATIO_2", 340) / 1000)); callMethod(param.thisObject, "setAnimParam", RADIUS, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RADIUS_2", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RADIUS_2", 225) / 1000)); callMethod(param.thisObject, "setAnimParam", ALPHA, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_ALPHA_2", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_ALPHA_2", 135) / 1000)); } case "OPEN_FROM_RECENTS" -> {// 3 callMethod(param.thisObject, "setAnimParam", RECT_CENTERX, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERX_3", 900) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERX_3", 270) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_CENTERY, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERY_3", 900) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERY_3", 270) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_WIDTH, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_WIDTH_3", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_WIDTH_3", 360) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_RATIO, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_RATIO_3", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_RATIO_3", 360) / 1000)); } case "CLOSE_TO_RECENTS" -> {// 4 callMethod(param.thisObject, "setAnimParam", RECT_CENTERX, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERX_4", 950) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERX_4", 315) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_CENTERY, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERY_4", 950) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERY_4", 315) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_WIDTH, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_WIDTH_4", 950) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_WIDTH_4", 315) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_RATIO, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_RATIO_4", 950) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_RATIO_4", 270) / 1000)); callMethod(param.thisObject, "setAnimParam", RADIUS, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RADIUS_4", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RADIUS_4", 270) / 1000)); callMethod(param.thisObject, "setAnimParam", ALPHA, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_ALPHA_4", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_ALPHA_4", 270) / 1000)); } case "CLOSE_TO_HOME" -> {// 5 callMethod(param.thisObject, "setAnimParam", RECT_CENTERX, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERX_5", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERX_5", 450) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_CENTERY, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERY_5", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERY_5", 450) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_WIDTH, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_WIDTH_5", 900) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_WIDTH_5", 450) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_RATIO, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_RATIO_5", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_RATIO_5", 370) / 1000)); callMethod(param.thisObject, "setAnimParam", RADIUS, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RADIUS_5", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RADIUS_5", 150) / 1000)); callMethod(param.thisObject, "setAnimParam", ALPHA, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_ALPHA_5", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_ALPHA_5", 420) / 1000)); } case "CLOSE_FROM_FEED" -> {// 6 callMethod(param.thisObject, "setAnimParam", RECT_CENTERX, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERX_6", 950) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERX_6", 378) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_CENTERY, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERY_6", 950) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERY_6", 378) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_WIDTH, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_WIDTH_6", 900) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_WIDTH_6", 405) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_RATIO, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_RATIO_6", 950) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_RATIO_6", 333) / 1000)); callMethod(param.thisObject, "setAnimParam", RADIUS, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RADIUS_6", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RADIUS_6", 180) / 1000)); callMethod(param.thisObject, "setAnimParam", ALPHA, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_ALPHA_6", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_ALPHA_6", 378) / 1000)); } case "APP_TO_APP" -> {// 7 callMethod(param.thisObject, "setAnimParam", RECT_CENTERX, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERX_7", 900) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERX_7", 315) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_CENTERY, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERY_7", 900) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERY_7", 315) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_WIDTH, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_WIDTH_7", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_WIDTH_7", 315) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_RATIO, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_RATIO_7", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_RATIO_7", 315) / 1000)); } case "START_FIRST_TASK" -> {// 8 callMethod(param.thisObject, "setAnimParam", RECT_CENTERX, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERX_8", 900) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERX_8", 180) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_CENTERY, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_CENTERY_8", 900) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_CENTERY_8", 180) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_WIDTH, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_WIDTH_8", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_WIDTH_8", 180) / 1000)); callMethod(param.thisObject, "setAnimParam", RECT_RATIO, ((float) mPrefsMap.getInt("home_title_custom_anim_param_damping_RECT_RATIO_8", 990) / 1000), ((float) mPrefsMap.getInt("home_title_custom_anim_param_stiffness_RECT_RATIO_8", 180) / 1000)); } default -> { } } param.setResult(null); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/BigIconCorner.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.title import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.getObjectField object BigIconCorner : BaseHook() { override fun init() { val maMlHostViewClass = loadClass("com.miui.home.launcher.maml.MaMlHostView") // if (!mPrefsMap.getBoolean("big_icon_corner")) return loadClass("com.miui.home.launcher.bigicon.BigIconUtil").methodFinder().filter { name == "getCroppedFromCorner" && parameterCount == 4 }.toList().createHooks { before { it.args[0] = 2 it.args[1] = 2 } } maMlHostViewClass.methodFinder().first { name == "getCornerRadius" }.createHook { before { it.result = it.thisObject.getObjectField("mEnforcedCornerRadius") as Float } } maMlHostViewClass.methodFinder().first { name == "computeRoundedCornerRadius" && parameterCount == 1 }.createHook { before { it.result = it.thisObject.getObjectField("mEnforcedCornerRadius") as Float } } loadClass("com.miui.home.launcher.LauncherAppWidgetHostView").methodFinder().first { name == "computeRoundedCornerRadius" && parameterCount == 1 }.createHook { before { it.result = it.thisObject.getObjectField("mEnforcedCornerRadius") as Float } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/DisableHideFile.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.title import android.content.ComponentName import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.IS_INTERNATIONAL_BUILD import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers object DisableHideFile : BaseHook() { override fun init() { if (IS_INTERNATIONAL_BUILD) return XposedHelpers.findAndHookConstructor( "com.miui.home.launcher.AppFilter", lpparam.classLoader, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val skippedItem = XposedHelpers.getObjectField( param.thisObject, "mSkippedItems" ) as HashSet skippedItem.removeIf { it.packageName == "com.google.android.documentsui" } } } ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/DisableHideTheme.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.title import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.IS_TABLET object DisableHideTheme: BaseHook() { override fun init() { if (!IS_TABLET) return hookAllMethods("com.miui.home.launcher.DeviceConfig", "needHideThemeManager", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = false } } ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/DownloadAnimation.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import com.sevtinge.cemiuiler.module.base.BaseHook; public class DownloadAnimation extends BaseHook { @Override public void init() { try{ hookAllMethods("com.miui.home.launcher.common.DeviceLevelUtils", "needMamlProgressIcon", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.miui.home.launcher.common.DeviceLevelUtils", "needRemoveDownloadAnimationDevice", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(false); } }); } catch (Exception e) { hookAllMethods("com.miui.home.launcher.common.CpuLevelUtils", "needMamlDownload", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/EnableIconMonetColor.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.title import android.annotation.SuppressLint import android.content.res.Resources import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.module.base.BaseXposedInit import de.robv.android.xposed.callbacks.XC_InitPackageResources object EnableIconMonetColor : BaseHook() { override fun init() {} @SuppressLint("DiscouragedApi") fun initResource(resParam: XC_InitPackageResources.InitPackageResourcesParam) { val monet = "system_accent1_100" val monoColorId = Resources.getSystem().getIdentifier(monet, "color", "android") var monoColor = Resources.getSystem().getColor(monoColorId, null) if (BaseXposedInit.mPrefsMap.getBoolean("home_other_use_edit_color")) { monoColor = mPrefsMap.getInt("home_other_your_color_qwq", -1) } resParam.res.setReplacement( "com.miui.home", "color", "monochrome_default", monoColor ) // val ColorEntriesId = Resources.getSystem().getStringArray() // val ColorEntries = Resources.getSystem().getStringArray(ColorEntriesId) // getInitPackageResourcesParam().res.setReplacement( // "com.miui.home", // "string", // ColorEntries.toString(), // "Monet" // ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/EnableIconMonoChrome.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import com.sevtinge.cemiuiler.module.base.BaseHook; public class EnableIconMonoChrome extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.launcher.graphics.MonochromeUtils", "isSupportMonochrome", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/FixAnimation.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import android.view.MotionEvent; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedHelpers; import kotlin.jvm.internal.Intrinsics; // from MIUI-EXTRA by Art-Chen public class FixAnimation extends BaseHook { private Object mAppToHomeAnim2Bak; private final Runnable mRunnable = () -> { }; public final Object getMAppToHomeAnim2Bak() { return mAppToHomeAnim2Bak; } public final void setMAppToHomeAnim2Bak(Object obj) { mAppToHomeAnim2Bak = obj; } public final Runnable getMRunnable() { return mRunnable; } @Override public void init() { Intrinsics.checkNotNull(lpparam); findAndHookMethod("com.miui.home.recents.NavStubView", "onInputConsumerEvent", MotionEvent.class, new MethodHook() { @Override protected void before(MethodHookParam param) { Intrinsics.checkNotNullParameter(param, "param"); setMAppToHomeAnim2Bak(XposedHelpers.getObjectField(param.thisObject, "mAppToHomeAnim2")); if (getMAppToHomeAnim2Bak() != null) { XposedHelpers.setObjectField(param.thisObject, "mAppToHomeAnim2", (Object) null); } } @Override protected void after(MethodHookParam param) { Intrinsics.checkNotNullParameter(param, "param"); Object obj = param.args[0]; Intrinsics.checkNotNull(obj, "null cannot be cast to non-null type android.view.MotionEvent"); MotionEvent motionEvent = (MotionEvent) obj; XposedLogUtils.logI("onInputConsumerEvent: Action: " + motionEvent.getAction() + ", return " + param.getResult() + ". x: " + motionEvent.getX() + " y: " + motionEvent.getY()); if (XposedHelpers.getObjectField(param.thisObject, "mAppToHomeAnim2") != null || getMAppToHomeAnim2Bak() == null) { return; } XposedHelpers.setObjectField(param.thisObject, "mAppToHomeAnim2", getMAppToHomeAnim2Bak()); } }); findAndHookMethod("com.miui.home.launcher.ItemIcon", "initPerformClickRunnable", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Intrinsics.checkNotNullParameter(param, "param"); param.setResult(getMRunnable()); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/HiddenAllTitle.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import com.sevtinge.cemiuiler.module.base.BaseHook; public class HiddenAllTitle extends BaseHook { @Override public void init() { /*用于隐藏应用名*/ findAndHookMethod("com.miui.home.launcher.ItemIcon", "setTitle", CharSequence.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(null); } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/IconScaleHook.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import android.annotation.SuppressLint; import android.graphics.Rect; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedHelpers; public class IconScaleHook extends BaseHook { @Override public void init() { Helpers.findAndHookMethod("com.miui.home.launcher.ShortcutIcon", lpparam.classLoader, "restoreToInitState", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { ViewGroup mIconContainer = (ViewGroup) XposedHelpers.getObjectField(param.thisObject, "mIconContainer"); if (mIconContainer == null || mIconContainer.getChildAt(0) == null) return; float multx = (float) Math.sqrt(mPrefsMap.getInt("home_title_icon_scale", 100) / 100f); mIconContainer.getChildAt(0).setScaleX(multx); mIconContainer.getChildAt(0).setScaleY(multx); } }); Helpers.findAndHookMethod("com.miui.home.launcher.ItemIcon", lpparam.classLoader, "onFinishInflate", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { float multx = (float) Math.sqrt(mPrefsMap.getInt("home_title_icon_scale", 100) / 100f); ViewGroup mIconContainer = (ViewGroup) XposedHelpers.getObjectField(param.thisObject, "mIconContainer"); if (mIconContainer != null && mIconContainer.getChildAt(0) != null) { mIconContainer.getChildAt(0).setScaleX(multx); mIconContainer.getChildAt(0).setScaleY(multx); mIconContainer.setClipToPadding(false); mIconContainer.setClipChildren(false); } if (multx > 1) { final TextView mMessage = (TextView) XposedHelpers.getObjectField(param.thisObject, "mMessage"); if (mMessage != null) mMessage.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override @SuppressLint("DiscouragedApi") public void afterTextChanged(Editable s) { int maxWidth = mMessage.getResources().getDimensionPixelSize(mMessage.getResources().getIdentifier("icon_message_max_width", "dimen", lpparam.packageName)); mMessage.measure(View.MeasureSpec.makeMeasureSpec(maxWidth, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(maxWidth, View.MeasureSpec.AT_MOST)); mMessage.setTranslationX(-mMessage.getMeasuredWidth() * (multx - 1) / 2f); mMessage.setTranslationY(mMessage.getMeasuredHeight() * (multx - 1) / 2f); } }); } XposedHelpers.setAdditionalInstanceField(param.thisObject, "mMessageAnimationOrig", XposedHelpers.getObjectField(param.thisObject, "mMessageAnimation")); XposedHelpers.setObjectField(param.thisObject, "mMessageAnimation", (Runnable) () -> { try { Runnable mMessageAnimationOrig = (Runnable) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mMessageAnimationOrig"); mMessageAnimationOrig.run(); boolean mIsShowMessageAnimation = XposedHelpers.getBooleanField(param.thisObject, "mIsShowMessageAnimation"); if (mIsShowMessageAnimation) { View mMessage = (View) XposedHelpers.getObjectField(param.thisObject, "mMessage"); mMessage.animate().cancel(); mMessage.animate().scaleX(multx).scaleY(multx).setStartDelay(0).start(); } } catch (Throwable t) { XposedLogUtils.logI(String.valueOf(t)); } }); // if (mult <= 1) return; // TextView mMessage = (TextView)XposedHelpers.getObjectField(param.thisObject, "mMessage"); // if (mMessage != null) { // int width = mMessage.getResources().getDimensionPixelSize(mMessage.getResources().getIdentifier("icon_message_max_width", "dimen", lpparam.packageName)); // mMessage.setTranslationX(-width/2f * (1f - 1f / mult)); // mMessage.setTranslationY(width/2f * (1f - 1f / mult)); // } } }); Helpers.findAndHookMethod("com.miui.home.launcher.ItemIcon", lpparam.classLoader, "getIconLocation", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { float multx = (float) Math.sqrt(mPrefsMap.getInt("home_title_icon_scale", 100) / 100f); Rect rect = (Rect) param.getResult(); if (rect == null) return; rect.right = rect.left + Math.round(rect.width() * multx); rect.bottom = rect.top + Math.round(rect.height() * multx); param.setResult(rect); } }); Helpers.findAndHookMethodSilently("com.miui.home.launcher.gadget.ClearButton", lpparam.classLoader, "onCreate", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { ViewGroup mIconContainer = (ViewGroup) XposedHelpers.getObjectField(param.thisObject, "mIconContainer"); if (mIconContainer == null || mIconContainer.getChildAt(0) == null) return; float multi = (float) Math.sqrt(mPrefsMap.getInt("home_title_icon_scale", 100) / 100f); mIconContainer.getChildAt(0).setScaleX(multi); mIconContainer.getChildAt(0).setScaleY(multi); } }); // Helpers.findAndHookMethod("com.miui.home.launcher.Folder", lpparam.classLoader, "onOpen", boolean.class, new MethodHook() { // @Override // protected void after(final MethodHookParam param) throws Throwable { // XposedHelpers.setFloatField(param.thisObject, "mItemIconToPreviewIconScale", -1.0f); // } // }); // // Helpers.findAndHookMethod("com.miui.home.launcher.Folder", lpparam.classLoader, "changeItemsInFolderDuringOpenAndCloseAnimation", float.class, new MethodHook() { // @Override // protected void after(final MethodHookParam param) throws Throwable { // float multx = (float)Math.sqrt(MainModule.mPrefs.getInt("launcher_icon_scale", 100) / 100f); // ViewGroup mContent = (ViewGroup)XposedHelpers.getObjectField(param.thisObject, "mContent"); // for (int i = 0; i < mContent.getChildCount(); i++) { // String cls = mContent.getChildAt(i).getClass().getSimpleName(); // if ("ItemIcon".equals(cls) || "ShortcutIcon".equals(cls) || "FolderIcon".equals(cls)) { // View iconContainer = (View)XposedHelpers.callMethod(mContent.getChildAt(i), "getIconContainer"); // float mult = (float)param.args[0] * multx; // iconContainer.setScaleX(mult); // iconContainer.setScaleY(mult); // } // } // } // }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/IconTitleColor.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.title import android.annotation.SuppressLint import android.content.Context import android.view.View import android.view.ViewGroup import android.widget.TextView import com.github.kyuubiran.ezxhelper.Log import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.findClass import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod object IconTitleColor : BaseHook() { @SuppressLint("DiscouragedApi") override fun init() { val value = mPrefsMap.getInt("home_title_title_color", -1) val launcherClass = "com.miui.home.launcher.Launcher".findClass() val shortcutInfoClass = "com.miui.home.launcher.ShortcutInfo".findClass() if (value == -1) return try { "com.miui.home.launcher.ItemIcon".hookAfterMethod( "onFinishInflate" ) { val mTitle = it.thisObject.getObjectField("mTitle") as TextView mTitle.setTextColor(value) } "com.miui.home.launcher.maml.MaMlWidgetView".hookAfterMethod( "onFinishInflate" ) { val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView mTitle.setTextColor(value) } "com.miui.home.launcher.LauncherMtzGadgetView".hookAfterMethod( "onFinishInflate" ) { val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView mTitle.setTextColor(value) } "com.miui.home.launcher.LauncherWidgetView".hookAfterMethod( "onFinishInflate" ) { val mTitle = it.thisObject.getObjectField("mTitleTextView") as TextView mTitle.setTextColor(value) } "com.miui.home.launcher.ShortcutIcon".hookAfterMethod( "fromXml", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java, shortcutInfoClass ) { val buddyIconView = it.args[3].callMethod("getBuddyIconView", it.args[2]) as View val mTitle = buddyIconView.getObjectField("mTitle") as TextView mTitle.setTextColor(value) } "com.miui.home.launcher.ShortcutIcon".hookAfterMethod( "createShortcutIcon", Int::class.javaPrimitiveType, launcherClass, ViewGroup::class.java ) { val buddyIcon = it.result as View val mTitle = buddyIcon.getObjectField("mTitle") as TextView mTitle.setTextColor(value) } "com.miui.home.launcher.common.Utilities".hookAfterMethod( "adaptTitleStyleToWallpaper", Context::class.java, TextView::class.java, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType ) { val mTitle = it.args[1] as TextView if (mTitle.id == mTitle.resources.getIdentifier("icon_title", "id", "com.miui.home")) { mTitle.setTextColor(value) } } } catch (e: Throwable) { Log.ex(e) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/LargeIconCornerRadius.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DisplayUtils; public class LargeIconCornerRadius extends BaseHook { Class mBigIconUtil; @Override public void init() { mBigIconUtil = findClassIfExists("com.miui.home.launcher.bigicon.BigIconUtil"); hookAllMethods(mBigIconUtil, "getCroppedFromCorner", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Context context = (Context) param.args[3]; Bitmap bitmap = (Bitmap) param.args[2]; Drawable drawable = new BitmapDrawable(context.getResources(), croppedCorners(bitmap, DisplayUtils.dip2px(context, mPrefsMap.getInt("home_large_icon_corner_radius", 32)))); param.setResult(drawable); } }); } public final Bitmap croppedCorners(Bitmap bitmap, float radius) { try { int width = bitmap.getWidth(); int height = bitmap.getHeight(); Paint mCornerPaint = new Paint(); mCornerPaint.setAntiAlias(true); mCornerPaint.setColor(-16777216); Bitmap createBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(createBitmap); canvas.drawARGB(0, 0, 0, 0); mCornerPaint.setXfermode(null); RectF rectF = new RectF(0.0f, 0.0f, width, height); canvas.drawRoundRect(rectF, radius, radius, mCornerPaint); mCornerPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); Rect rect = new Rect(0, 0, width, height); canvas.drawBitmap(bitmap, rect, rect, mCornerPaint); bitmap.recycle(); return createBitmap; } catch (Exception unused) { return bitmap; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/NewInstallIndicator.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import com.sevtinge.cemiuiler.module.base.BaseHook; public class NewInstallIndicator extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.launcher.TitleTextView", "updateNewInstallIndicator", boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(null); } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/PerfectIcon.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import android.content.pm.LauncherActivityInfo; import com.sevtinge.cemiuiler.module.base.BaseHook; public class PerfectIcon extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.library.compat.LauncherActivityInfoCompat", "getIconResource", LauncherActivityInfo.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(0); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/TitleFontSize.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import android.annotation.SuppressLint; import android.util.TypedValue; import android.widget.TextView; import com.sevtinge.cemiuiler.module.base.BaseHook; public class TitleFontSize extends BaseHook { @Override public void init() { hookAllMethods("com.miui.home.launcher.common.Utilities", "adaptTitleStyleToWallpaper", new MethodHook() { @SuppressLint("DiscouragedApi") @Override protected void after(MethodHookParam param) { TextView mTitle = (TextView) param.args[1]; if (mTitle != null && mTitle.getId() == mTitle.getResources().getIdentifier("icon_title", "id", "com.miui.home")) { mTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, mPrefsMap.getInt("home_title_font_size", 12)); } } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/title/TitleMarquee.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.title; import android.text.TextUtils; import android.widget.TextView; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class TitleMarquee extends BaseHook { @Override public void init() { Class mItemIcon = findClassIfExists("com.miui.home.launcher.ItemIcon"); findAndHookMethod(mItemIcon, "onFinishInflate", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { TextView mTitle = (TextView) XposedHelpers.getObjectField(param.thisObject, "mTitle"); mTitle.setEllipsize(TextUtils.TruncateAt.MARQUEE); mTitle.setHorizontalFadingEdgeEnabled(true); mTitle.setSingleLine(); mTitle.setMarqueeRepeatLimit(-1); mTitle.setSelected(true); mTitle.setHorizontallyScrolling(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/widget/AllWidgetAnimation.java ================================================ package com.sevtinge.cemiuiler.module.hook.home.widget; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class AllWidgetAnimation extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.home.launcher.LauncherWidgetView", "isUseTransitionAnimation", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); findAndHookMethod("com.miui.home.launcher.maml.MaMlWidgetView", "isUseTransitionAnimation", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/widget/AllowMoveAllWidgetToMinus.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.widget import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.getObjectFieldOrNull object AllowMoveAllWidgetToMinus : BaseHook() { override fun init() { // if (!mPrefsMap.getBoolean("home_widget_to_minus")) return try { loadClass("com.miui.home.launcher.widget.MIUIWidgetHelper").methodFinder().first { name == "canDragToPa" && parameterCount == 2 }.createHook { before { val dragInfo = it.args[1].callMethod("getDragInfo") val i = dragInfo?.getObjectField("spanX") val launcherCallbacks = it.args[0].callMethod("getLauncherCallbacks") val dragController = it.args[0].callMethod("getDragController") val isDraggingFromAssistant = dragController?.callMethod("isDraggingFromAssistant") as Boolean val isDraggingToAssistant = dragController.callMethod("isDraggingToAssistant") as Boolean it.result = launcherCallbacks != null && !isDraggingFromAssistant && !isDraggingToAssistant && i != 1 } } } catch (e: Exception) { loadClass("com.miui.home.launcher.Workspace").methodFinder().first { name == "canDragToPa" }.createHook { before { val currentDragObject = it.thisObject.getObjectFieldOrNull("mDragController") ?.callMethod("getCurrentDragObject") val dragInfo = currentDragObject?.callMethod("getDragInfo") val i = dragInfo?.getObjectField("spanX") val launcherCallbacks = it.thisObject.getObjectFieldOrNull("mLauncher") ?.callMethod("getLauncherCallbacks") val isDraggingFromAssistant = it.thisObject.getObjectFieldOrNull("mDragController") ?.callMethod("isDraggingFromAssistant") as Boolean val isDraggingToAssistant = it.thisObject.getObjectFieldOrNull("mDragController") ?.callMethod("isDraggingToAssistant") as Boolean it.result = launcherCallbacks != null && !isDraggingFromAssistant && !isDraggingToAssistant && i != 1 } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/widget/AlwaysShowMiuiWidget.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.widget import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.setObjectField import de.robv.android.xposed.XC_MethodHook object AlwaysShowMiuiWidget : BaseHook() { override fun init() { var hook1: XC_MethodHook.Unhook? = null var hook2: XC_MethodHook.Unhook? = null try { loadClass("com.miui.home.launcher.widget.WidgetsVerticalAdapter").methodFinder().first { name == "buildAppWidgetsItems" } } catch (e: Exception) { loadClass("com.miui.home.launcher.widget.BaseWidgetsVerticalAdapter").methodFinder().first { name == "buildAppWidgetsItems" } }.createHook { before { hook1 = loadClass("com.miui.home.launcher.widget.MIUIAppWidgetInfo").methodFinder() .first { name == "initMiuiAttribute" && parameterCount == 1 }.createHook { after { it.thisObject.setObjectField("isMIUIWidget", false) } } hook2 = loadClass("com.miui.home.launcher.MIUIWidgetUtil").methodFinder().first { name == "isMIUIWidgetSupport" }.createHook { after { it.result = false } } } after { hook1?.unhook() hook2?.unhook() } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/widget/HideWidgetTitles.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.widget import android.view.View import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.hookAfterMethod import java.util.function.Predicate object HideWidgetTitles : BaseHook() { override fun init() { val maMlWidgetInfo = loadClass("com.miui.home.launcher.maml.MaMlWidgetInfo") loadClass("com.miui.home.launcher.LauncherAppWidgetHost").methodFinder().first { name == "createLauncherWidgetView" && parameterCount == 4 }.createHook { after { val view = it.result as Any view.callMethod("getTitleView")?.callMethod("setVisibility", View.GONE) } } "com.miui.home.launcher.Launcher".hookAfterMethod( "addMaMl", maMlWidgetInfo, Boolean::class.java, Predicate::class.java ) { val view = it.result as Any view.callMethod("getTitleView")?.callMethod("setVisibility", View.GONE) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/home/widget/ResizableWidgets.kt ================================================ package com.sevtinge.cemiuiler.module.hook.home.widget import android.appwidget.AppWidgetProviderInfo import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers object ResizableWidgets : BaseHook() { override fun init() { Helpers.hookAllMethods( "android.appwidget.AppWidgetHostView", null, "getAppWidgetInfo", object : MethodHook() { @Throws(Throwable::class) override fun after(param: MethodHookParam) { val widgetInfo = param.result as AppWidgetProviderInfo widgetInfo.resizeMode = AppWidgetProviderInfo.RESIZE_VERTICAL or AppWidgetProviderInfo.RESIZE_HORIZONTAL widgetInfo.minHeight = 0 widgetInfo.minWidth = 0 widgetInfo.minResizeHeight = 0 widgetInfo.minResizeWidth = 0 param.result = widgetInfo } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/incallui/AnswerInHeadUp.java ================================================ package com.sevtinge.cemiuiler.module.hook.incallui; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import miui.process.ForegroundInfo; import miui.process.ProcessManager; public class AnswerInHeadUp extends BaseHook { @Override public void init() { findAndHookMethod("com.android.incallui.InCallPresenter", "answerIncomingCall", Context.class, String.class, int.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { boolean showUi = (boolean) param.args[3]; if (showUi) { ForegroundInfo foregroundInfo = ProcessManager.getForegroundInfo(); if (foregroundInfo != null) { String topPackage = foregroundInfo.mForegroundPackageName; /*if (!"com.miui.home".equals(topPackage)) { param.args[3] = false; }*/ } } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/incallui/HideCrbt.java ================================================ package com.sevtinge.cemiuiler.module.hook.incallui; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; public class HideCrbt extends BaseHook { Class loadClass; public void init() { loadClass = findClassIfExists("com.android.incallui.Call"); try { hookAllMethods(loadClass, "getVideoCall", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(null); } }); findAndHookMethod(loadClass, "setPlayingVideoCrbt", int.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.args[0] = 0; param.args[1] = Boolean.FALSE; } }); /*hookAllMethods(loadClass, "setPlayingVideoCrbt", new MethodHook(){ Integer.TYPE, Boolean.TYPE, beforeHookedMethod() });*/ } catch (Exception e) { XposedLogUtils.logI("method hooked failed! " + e); } } /*public final void beforeHookedMethod(XC_MethodHook.MethodHookParam methodHookParam) { HideCrbt.super.before(methodHookParam); methodHookParam.args[0]=0; methodHookParam.args[1]=Boolean.FALSE; }*/ } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/joyose/DisableCloudControl.java ================================================ package com.sevtinge.cemiuiler.module.hook.joyose; /*import static com.sevtinge.cemiuiler.module.hook.joyose.JoyoseDexKit.mJoyoseResultMethodsMap; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.lang.reflect.Method; import java.util.List; import java.util.Objects; import io.luckypray.dexkit.descriptor.member.DexMethodDescriptor; public class DisableCloudControl extends BaseHook { // Class mCloud; Method cloudControl; @Override public void init() { try { List result = Objects.requireNonNull(JoyoseDexKit.mJoyoseResultMethodsMap.get("CloudControl")); for (DexMethodDescriptor descriptor : result) { cloudControl = descriptor.getMethodInstance(lpparam.classLoader); if (cloudControl.getReturnType() == void.class) { hookMethod(cloudControl, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(null);// 2 } }); } } } catch (Throwable e) { e.printStackTrace(); } *//*hookMethod(cloudControl, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(null);//2 } });*//* // mCloud = findClassIfExists("com.xiaomi.joyose.cloud.g$a"); } }*/ ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/joyose/DisableCloudControl.kt ================================================ package com.sevtinge.cemiuiler.module.hook.joyose import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object DisableCloudControl : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals("job exist, sync local...") returnType = "void" } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(null) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/joyose/EnableGpuTuner.java ================================================ package com.sevtinge.cemiuiler.module.hook.joyose; /*import static com.sevtinge.cemiuiler.module.hook.joyose.JoyoseDexKit.mJoyoseResultMethodsMap; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.lang.reflect.Method; import java.util.List; import java.util.Objects; import io.luckypray.dexkit.descriptor.member.DexMethodDescriptor; public class EnableGpuTuner extends BaseHook { // Class mCloud; Method gpuTuner; @Override public void init() { try { List result = Objects.requireNonNull(JoyoseDexKit.mJoyoseResultMethodsMap.get("GpuTuner")); for (DexMethodDescriptor descriptor : result) { gpuTuner = descriptor.getMethodInstance(lpparam.classLoader); if (gpuTuner.getReturnType() == boolean.class) { hookMethod(gpuTuner, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true);// 2 } }); } } } catch (Throwable e) { e.printStackTrace(); } *//*hookMethod(cloudControl, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(null);//2 } });*//* // mCloud = findClassIfExists("com.xiaomi.joyose.cloud.g$a"); } }*/ ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/joyose/EnableGpuTuner.kt ================================================ package com.sevtinge.cemiuiler.module.hook.joyose import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object EnableGpuTuner : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals("GPUTUNER_SWITCH") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/lbe/DisableClipboardTip.kt ================================================ package com.sevtinge.cemiuiler.module.hook.lbe import android.content.Context import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.os.Build import android.widget.Toast import com.sevtinge.cemiuiler.R import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers import de.robv.android.xposed.callbacks.XC_LoadPackage object DisableClipboardTip : BaseHook() { override fun init() { if (!lpparam.packageName.equals("com.lbe.security.miui")) return val permissionRequestClass = XposedHelpers.findClass("com.lbe.security.sdk.PermissionRequest", lpparam.classLoader) val mDisableClipboardTip = mPrefsMap.getBoolean("lbe_disable_clipboard_tip") XposedHelpers.findAndHookMethod( "com.lbe.security.ui.SecurityPromptHandler", lpparam.classLoader, "handleNewRequest", permissionRequestClass, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val permissionRequest = param.args[0] val permission: Long = XposedHelpers.callMethod(permissionRequest, "getPermission") as Long // PermissionManager.PERM_ID_READ_CLIPBOARD if (permission == 274877906944L) { val packageName = XposedHelpers.callMethod(permissionRequest, "getPackage") as String val context = XposedHelpers.getObjectField(param.thisObject, "mContext") as Context val appName = getAppName(context, packageName) val modRes = Helpers.getModuleRes(context) if (!mDisableClipboardTip) { Toast.makeText(context, "$appName ${modRes.getString(R.string.lbe_clipboard_tip)}", Toast.LENGTH_SHORT).show() } hideDialog(lpparam, packageName, param) XposedLogUtils.logI(" $packageName -> $appName read clipboard.") } } }) } fun getAppName(context: Context, packageName: String): String { val pm: PackageManager = context.applicationContext.packageManager val ai: ApplicationInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { pm.getApplicationInfo(packageName, PackageManager.ApplicationInfoFlags.of(0)) } else { pm.getApplicationInfo(packageName, 0) } return (pm.getApplicationLabel(ai)) as String } fun hideDialog( lpparam: XC_LoadPackage.LoadPackageParam, packageName: String, param: XC_MethodHook.MethodHookParam ) { val clipData = XposedHelpers.findClass( "com.lbe.security.utility.AnalyticsHelper", lpparam.classLoader ) val hashMap = HashMap() hashMap["pkgName"] = packageName hashMap["count"] = "click" XposedHelpers.callStaticMethod( clipData, "recordCountEvent", "clip", "ask_allow", hashMap ) XposedHelpers.callMethod(param.thisObject, "gotChoice", 3, true, true) XposedHelpers.callMethod(param.thisObject, "onStop") } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/market/DeviceModify.java ================================================ package com.sevtinge.cemiuiler.module.hook.market; import android.os.Build; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class DeviceModify extends BaseHook { String mDevice; String mModel; String mManufacturer; @Override public void init() { if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 101) { // 13u mDevice = "ishtar"; mModel = "2304FPN6DC"; mManufacturer = "Xiaomi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 102) { // 14p mDevice = "shennong"; mModel = "23116PN5BC"; mManufacturer = "Xiaomi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 103) { // 14 mDevice = "houji"; mModel = "23127PN0CC"; mManufacturer = "Xiaomi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 153) { // civi3 mDevice = "yuechu"; mModel = "23046PNC9C"; mManufacturer = "Xiaomi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 223) { // f3 mDevice = "babylon"; mModel = "2308CPXD0C"; mManufacturer = "Xiaomi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 190) { // alpha mDevice = "avenger"; mModel = "MIX Alpha"; mManufacturer = "Xiaomi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 191) { // alpha mDevice = "draco"; mModel = "MIX Alpha"; mManufacturer = "Xiaomi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 208) { // pad6m mDevice = "yudi"; mModel = "2307BRPDCC"; mManufacturer = "Xiaomi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 307) { // k60u mDevice = "corot"; mModel = "23078RKD5C"; mManufacturer = "Redmi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 309) { // k70p mDevice = "manet"; mModel = "23117RK66C"; mManufacturer = "Redmi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 351) { // k70e mDevice = "duchamp"; mModel = "23113RKC6C"; mManufacturer = "Redmi"; } else if (mPrefsMap.getStringAsInt("market_device_modify_new", 0) == 334) { // n13pp mDevice = "zircon"; mModel = "23090RA98C"; mManufacturer = "Redmi"; } findAndHookConstructor("com.xiaomi.market.MarketApp", new MethodHook() { @Override protected void before(MethodHookParam param) { XposedHelpers.setStaticObjectField(Build.class, "DEVICE", mDevice); XposedHelpers.setStaticObjectField(Build.class, "MODEL", mModel); XposedHelpers.setStaticObjectField(Build.class, "MANUFACTURER", mManufacturer); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/market/NewIcon.java ================================================ package com.sevtinge.cemiuiler.module.hook.market; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.lang.reflect.Method; import java.util.List; import java.util.Objects; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedBridge; public class NewIcon extends BaseHook { static Method isDesktopSupportOperationIcon; @Override public void init() { /* try { List result = Objects.requireNonNull(MarketDexKit.mMarketResultMethodsMap.get("DesktopSupportOperationIcon")); for (DexMethodDescriptor descriptor : result) { isDesktopSupportOperationIcon = descriptor.getMethodInstance(lpparam.classLoader); XposedLogUtils.logI("isDesktopSupportOperationIcon method is " + isDesktopSupportOperationIcon); if (isDesktopSupportOperationIcon.getReturnType() == boolean.class) { XposedBridge.hookMethod(isDesktopSupportOperationIcon, XC_MethodReplacement.returnConstant(false)); } } } catch (Throwable e) { e.printStackTrace(); } hookAllMethods("com.xiaomi.market.util.FileUtils", "ensureExternalIconDir", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(false); } });*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/mediaeditor/FilterManagerAll.kt ================================================ package com.sevtinge.cemiuiler.module.hook.mediaeditor import android.os.Build import com.github.kyuubiran.ezxhelper.ClassLoaderProvider.safeClassLoader import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.ClassUtils.setStaticObject import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.api.LazyClass.AndroidBuildCls import org.luckypray.dexkit.query.enums.StringMatchType object FilterManagerAll : BaseHook() { private lateinit var device: String private val methodResult by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("wayne") } }.filter { it.isMethod }.map { it.getMethodInstance(safeClassLoader) }.toTypedArray().firstOrNull() } override fun init() { /*val result = mMediaEditorResultMethodsMap["FilterManager"]!! val methodResult = result MethodFinder.fromArray(methodResult).first { returnType == List::class.java || (parameterCount == 1 && parameterTypes[0] == Bundle::class.java) }*/ methodResult?.createHook { before { if (!this@FilterManagerAll::device.isInitialized) { device = Build.DEVICE } setStaticObject(AndroidBuildCls, "DEVICE", "wayne") } after { setStaticObject(AndroidBuildCls, "DEVICE", device) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/mediaeditor/UnlockMinimumCropLimitNew.kt ================================================ package com.sevtinge.cemiuiler.module.hook.mediaeditor import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import java.lang.reflect.Modifier object UnlockMinimumCropLimitNew : BaseHook() { private val mScreenCropViewMethodToNew by lazy { dexKitBridge.findMethod { matcher { declaredClass { addUsingStringsEquals("not in bound") } usingNumbers(0.5f, 200) returnType = "int" modifiers = Modifier.FINAL } }.map { it.getMethodInstance(EzXHelper.classLoader) }.toList() } private val mScreenCropViewMethodToOld by lazy { dexKitBridge.findMethod { matcher { declaredClass { addUsingStringsEquals("fixImageBounds %f,%f") } usingNumbers(0.5f, 200) returnType = "int" modifiers = Modifier.FINAL } }.firstOrNull()?.getMethodInstance(EzXHelper.safeClassLoader) } override fun init() { mScreenCropViewMethodToNew.createHooks { returnConstant(0) } if (mScreenCropViewMethodToOld != null) { mScreenCropViewMethodToOld!!.createHook { returnConstant(0) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/milink/UnlockMiShare.java ================================================ package com.sevtinge.cemiuiler.module.hook.milink; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class UnlockMiShare extends BaseHook { @Override public void init() { hookAllMethods("com.miui.circulate.world.auth.AuthUtil", "doPermissionCheck", new MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) { param.setResult(null); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/mirror/UnlockMiuiPlus.java ================================================ package com.sevtinge.cemiuiler.module.hook.mirror; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class UnlockMiuiPlus extends BaseHook { @Override public void init() { findAndHookMethod("com.xiaomi.mirror.utils.SystemUtils", "isModelSupport", Context.class, new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/misettings/CustomRefreshRate.kt ================================================ package com.sevtinge.cemiuiler.module.hook.misettings import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.MemberExtensions.isFinal import com.github.kyuubiran.ezxhelper.MemberExtensions.isStatic import com.github.kyuubiran.ezxhelper.finders.FieldFinder.`-Static`.fieldFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import org.luckypray.dexkit.query.enums.StringMatchType object CustomRefreshRate : BaseHook() { private val resultMethod by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("btn_preferce_category") } } } override fun init() { /*val result1 = MiSettingsDexKit.mMiSettingsResultMethodsMap!!["category"] val result2 = MiSettingsDexKit.mMiSettingsResultClassMap!!["refresh"]*/ val resultClass = loadClass("com.xiaomi.misettings.display.RefreshRate.RefreshRateActivity") resultMethod.first().getMethodInstance(EzXHelper.classLoader).createHook { before { it.args[0] = true } } /*resultClass.map { it.getClassInstance(EzXHelper.classLoader).fieldFinder() .toList().forEach { field -> if (field.isFinal && field.isStatic) { field.isAccessible = true field.set(null, true) } } }*/ resultClass.declaredFields.first { field -> field.isFinal && field.isStatic }.apply { isAccessible = true }.set(null, true) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/misettings/ShowMoreFpsList.kt ================================================ package com.sevtinge.cemiuiler.module.hook.misettings import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object ShowMoreFpsList : BaseHook() { override fun init() { loadClass("miui.util.FeatureParser").methodFinder().first { name == "getIntArray" }.createHook { before { if (it.args[0] == "fpsList") { it.result = intArrayOf(144, 120, 90, 60, 30) } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/mishare/NoAutoTurnOff.kt ================================================ package com.sevtinge.cemiuiler.module.hook.mishare import com.github.kyuubiran.ezxhelper.EzXHelper.classLoader import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.api.BlurDraw.getValueByFields import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XposedHelpers import java.lang.reflect.Modifier object NoAutoTurnOff : BaseHook() { private val nullMethod by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("EnabledState", "mishare_enabled") } }.map { it.getMethodInstance(classLoader) }.toList() } private val null2Method by lazy { dexKitBridge.findMethod { matcher { declaredClass { addUsingStringsEquals("mishare:advertise_lock", "power") } paramCount = 2 modifiers = Modifier.STATIC } }.map { it.getMethodInstance(classLoader) }.toList() } private val null3Method by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("com.miui.mishare.action.GRANT_NFC_TOUCH_PERMISSION") usingNumbers(600000L) modifiers = Modifier.PRIVATE } }.map { it.getMethodInstance(classLoader) }.toList() } private val toastMethod by lazy { dexKitBridge.findMethod { matcher { declaredClass { addUsingStringsEquals("null context", "cta_agree") } returnType = "boolean" paramTypes = listOf("android.content.Context", "java.lang.String") paramCount = 2 } }.map { it.getMethodInstance(classLoader) }.toList() } override fun init() { val nullClass = dexKitBridge.findClass { matcher { addUsingStringsEquals("NfcShareTaskManager", "task out of limit type ") } }.map { it.getInstance(classLoader) }.first() val nullField = dexKitBridge.findField { matcher { declaredClass(nullClass) modifiers = Modifier.STATIC } }.map { it.getFieldInstance(classLoader) }.first() // 禁用小米互传功能自动关闭部分 nullMethod.createHooks { before { it.result = null } } try { null2Method.createHooks { before { it.result = null } } } catch (_: Throwable) { } try { null3Method.createHooks { after { val fieldNames = ('a'..'z').map { name -> name.toString() } val getField = getValueByFields(it.thisObject, fieldNames) ?: return@after XposedHelpers.callMethod(getField, "removeCallbacks", it.thisObject) XposedLogUtils.logI("null3Method hook success, $getField") } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, "null3Method hook failed", t) } try { XposedLogUtils.logI("$nullField") XposedHelpers.setStaticIntField(nullClass, nullField.name, 999999999) XposedLogUtils.logI(TAG, "nullField hook success.") } catch (t: Throwable) { XposedLogUtils.logE(TAG, "nullField hook failed", t) } // 干掉小米互传十分钟倒计时 Toast toastMethod.createHooks { before { param -> if (param.args[1].equals("security_agree")) { param.result = false } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/mishare/UnlockTurboMode.kt ================================================ package com.sevtinge.cemiuiler.module.hook.mishare import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object UnlockTurboMode : BaseHook() { private val turboModeMethod by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("DeviceUtil", "xiaomi.hardware.p2p_160m") } }.map { it.getMethodInstance(EzXHelper.classLoader) }.first() } override fun init() { turboModeMethod.createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/miwallpaper/UnlockSuperWallpaper.java ================================================ package com.sevtinge.cemiuiler.module.hook.miwallpaper; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class UnlockSuperWallpaper extends BaseHook { @Override public void init() { findAndHookMethod("com.miui.superwallpaper.SuperWallpaperUtils", "initEnableSuperWallpaper", Context.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); XposedHelpers.setStaticBooleanField(findClassIfExists("com.miui.superwallpaper.SuperWallpaperUtils"), "sEnableSuperWallpaper", true); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/mms/DisableAd.kt ================================================ package com.sevtinge.cemiuiler.module.hook.mms import android.content.Context import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object DisableAd : BaseHook() { override fun init() { try { dexKitBridge.findClass { matcher { addUsingStringsEquals("Unknown type of the message: ") } }.firstOrNull()?.getInstance(EzXHelper.classLoader)?.methodFinder()?.first { name == "j" }?.createHook { returnConstant(false) } /*val result: List = Objects.requireNonNull>( MmsDexKit.mMmsResultClassMap["DisableAd"] ) for (descriptor in result) { val enableAds: Class<*> = descriptor.getClassInstance(lpparam.classLoader) log("EnableAds class is $enableAds") findAndHookMethod(enableAds, "j", object : MethodHook() { @Throws(Throwable::class) override fun before(param: MethodHookParam) { param.setResult(false) } }) }*/ } catch (e: Throwable) { XposedLogUtils.logE(TAG, e) } findAndHookMethod("com.miui.smsextra.ui.BottomMenu", "allowMenuMode", Context::class.java, object : MethodHook() { @Throws(Throwable::class) override fun before(param: MethodHookParam) { param.setResult(false) } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/mtb/BypassAuthentication.kt ================================================ package com.sevtinge.cemiuiler.module.hook.mtb import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.setObjectField object BypassAuthentication : BaseHook() { override fun init() { val mModemTestBoxClass = loadClass("com.xiaomi.mtb.activity.ModemTestBoxMainActivity") runCatching { loadClass("com.xiaomi.mtb.MtbApp").methodFinder().first { name == "setMiServerPermissionClass" }.createHook { before { it.args[0] = 0 } } } runCatching { mModemTestBoxClass.methodFinder().first { name == "updateClass" }.createHook { before { it.args[0] = 0 it.thisObject.setObjectField("mClassNet", 0) } } } runCatching { mModemTestBoxClass.methodFinder().first { name == "initClassProduct" }.createHook { after { it.thisObject.setObjectField("mClassProduct", 0) } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/mtb/IsUserBuild.kt ================================================ package com.sevtinge.cemiuiler.module.hook.mtb import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object IsUserBuild : BaseHook() { override fun init() { loadClass("com.xiaomi.mtb.MtbUtils").methodFinder().first { name == "IsUserBuild" }.createHook { returnConstant(false) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/music/DisableAd.java ================================================ package com.sevtinge.cemiuiler.module.hook.music; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import com.sevtinge.cemiuiler.module.base.BaseHook; public class DisableAd extends BaseHook { Class mCloud; @Override // by @Yife Playte public void init() { try { findAndHookMethod("com.tencent.qqmusiclite.activity.SplashAdActivity", "onCreate", android.os.Bundle.class, new MethodHook() { @Override protected void after(MethodHookParam param) { try { Class clazz = findClassIfExists("android.app.Activity"); clazz.getMethod("finish").invoke(param.thisObject); } catch (Throwable e) { LogD(TAG, e); } } }); } catch (Throwable e) { LogD(TAG, e); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/networkboost/LinkTurboToast.java ================================================ package com.sevtinge.cemiuiler.module.hook.networkboost; import com.sevtinge.cemiuiler.module.base.BaseHook; public class LinkTurboToast extends BaseHook { @Override public void init() { findAndHookMethod("com.xiaomi.NetworkBoost.slaservice.SLAToast", "setLinkTurboStatus", boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.args[0] = false; } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/nfc/AllowInformationScreen.kt ================================================ package com.sevtinge.cemiuiler.module.hook.nfc import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class AllowInformationScreen : BaseHook() { override fun init() { loadClass("com.android.nfc.NfcService").methodFinder().filterByName("sendMessage").first().createHook { before { if (it.args[1] == 2 || it.args[1] == 4) { it.args[1] = 8 } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/nfc/DisableSound.java ================================================ package com.sevtinge.cemiuiler.module.hook.nfc; import com.sevtinge.cemiuiler.module.base.BaseHook; public class DisableSound extends BaseHook { @Override public void init() { findAndHookMethod("com.android.nfc.NfcService", "initSoundPool", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(null); } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/AllAsSystemApp.kt ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller import android.content.pm.ApplicationInfo import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.closeDexKit import com.sevtinge.cemiuiler.utils.DexKit.initDexKit import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object AllAsSystemApp : BaseHook() { private val systemMethod by lazy { dexKitBridge.findMethod { matcher { paramTypes = listOf("android.content.pm.ApplicationInfo") returnType = "boolean" } }.map { it.getMethodInstance(EzXHelper.safeClassLoader) } } override fun init() { /*dexKitBridge.findMethod { matcher { methodParamTypes = arrayOf("Landroid/content/pm/ApplicationInfo;") methodReturnType = "boolean" } }.forEach { it.getMethodInstance(lpparam.classLoader).createHook { before { param -> (param.args[0] as ApplicationInfo).flags = (param.args[0] as ApplicationInfo).flags.or(ApplicationInfo.FLAG_SYSTEM) } } }*/ systemMethod.createHooks { before { param -> (param.args[0] as ApplicationInfo).flags = (param.args[0] as ApplicationInfo).flags.or(ApplicationInfo.FLAG_SYSTEM) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/DisableAD.kt ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object DisableAD : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals("ads_enable") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(false) } dexKitBridge.findMethod { matcher { addUsingStringsEquals("app_store_recommend") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(false) } dexKitBridge.findMethod { matcher { addUsingStringsEquals("virus_scan_install") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(false) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/DisableCountChecking.kt ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object DisableCountChecking : BaseHook() { override fun init() { loadClass("com.miui.packageInstaller.model.RiskControlRules").methodFinder().first { name == "getCurrentLevel" }.createHook { returnConstant(0) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/DisableSafeModelTip.kt ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.findClassOrNull import com.sevtinge.cemiuiler.utils.setBooleanField object DisableSafeModelTip : BaseHook() { override fun init() { /*val result = Objects.requireNonNull( mPackageInstallerResultMethodsMap!!["DisableSafeModelTip"] ) for (descriptor in result) { val mDisableSafeModelTip = descriptor.getMethodInstance(lpparam.classLoader) mDisableSafeModelTip.createHook { returnConstant(false) } }*/ dexKitBridge.findMethod { matcher { addUsingStringsEquals("android.provider.MiuiSettings\$Ad") } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(false) } // 屏蔽每 30 天提示开启安全守护的弹窗(已知问题:完成和打开按钮无反应) /*val result2 = Objects.requireNonNull( mPackageInstallerResultMethodsMap!!["Disable30DaysDialog"] ) for (descriptor in result2) { val mDisableSafeModelTip = descriptor.getMethodInstance(lpparam.classLoader) mDisableSafeModelTip.createHook { returnConstant(null) } }*/ var letter = 'a' for (i in 0..25) { try { val classIfExists = "com.miui.packageInstaller.ui.listcomponets.${letter}0".findClassOrNull() classIfExists?.let { it.methodFinder().filterByName("a").first().createHook { after { hookParam -> try { hookParam.thisObject.setBooleanField("m", false) } catch (_: Throwable) { hookParam.thisObject.setBooleanField("l", false) } } } } } catch (t: Throwable) { letter++ } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/DisplayMoreApkInfo.java ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.res.Resources; import android.text.TextUtils; import android.view.Gravity; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DisplayUtils; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.Field; import java.lang.reflect.Method; import de.robv.android.xposed.XposedHelpers; public class DisplayMoreApkInfo extends BaseHook { Class mApkInfo; Class mAppInfoViewObject; @Override public void init() { mApkInfo = findClassIfExists("com.miui.packageInstaller.model.ApkInfo"); mAppInfoViewObject = findClassIfExists("com.miui.packageInstaller.ui.listcomponets.AppInfoViewObject"); if (mAppInfoViewObject != null) { Class ViewHolderClass = findClassIfExists("com.miui.packageInstaller.ui.listcomponets.AppInfoViewObject$ViewHolder"); Method[] methods = XposedHelpers.findMethodsByExactParameters(mAppInfoViewObject, void.class, ViewHolderClass); if (methods.length == 0) { XposedLogUtils.logI("AppInfoDuringMiuiInstallHook", "Cannot find appropriate method"); return; } Field[] fields = mAppInfoViewObject.getDeclaredFields(); String apkInfoFieldName = null; for (Field field : fields) if (mApkInfo.isAssignableFrom(field.getType())) { apkInfoFieldName = field.getName(); break; } if (apkInfoFieldName == null) return; String finalApkInfoFieldName = apkInfoFieldName; hookMethod(methods[0], new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Object viewHolder = param.args[0]; if (viewHolder == null) return; TextView tvAppSize = (TextView) XposedHelpers.callMethod(viewHolder, "getAppSize"); if (tvAppSize == null) return; Object apkInfo = XposedHelpers.getObjectField(param.thisObject, finalApkInfoFieldName); ApplicationInfo mAppInfo = (ApplicationInfo) XposedHelpers.callMethod(apkInfo, "getInstalledPackageInfo"); PackageInfo mPkgInfo = (PackageInfo) XposedHelpers.callMethod(apkInfo, "getPackageInfo"); Resources modRes = Helpers.getModuleRes(tvAppSize.getContext()); LinearLayout layout = (LinearLayout) tvAppSize.getParent(); layout.removeAllViews(); ViewGroup mRootView = (ViewGroup) layout.getParent(); ImageView mRoundImageView = (ImageView) mRootView.getChildAt(0); TextView mAppNameView = (TextView) mRootView.getChildAt(1); mRootView.removeAllViews(); LinearLayout linearLayout = new LinearLayout(mRootView.getContext()); linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setGravity(Gravity.CENTER); linearLayout.setLayoutParams(new LinearLayout.LayoutParams(-1, -1)); LinearLayout.LayoutParams AppNameViewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); AppNameViewParams.setMargins(0, DisplayUtils.dip2px(mRootView.getContext(), 10), 0, 0); mAppNameView.setLayoutParams(AppNameViewParams); mAppNameView.setGravity(Gravity.CENTER); LinearLayout linearLayout2 = new LinearLayout(mRootView.getContext()); linearLayout2.setOrientation(LinearLayout.VERTICAL); linearLayout2.setGravity(Gravity.CENTER); linearLayout2.setPadding(0, DisplayUtils.dip2px(mRootView.getContext(), 10), 0, 0); linearLayout2.setLayoutParams(new LinearLayout.LayoutParams(-1, -1)); TextView mAppVersionNameView = new TextView(mRootView.getContext()); TextView mAppVersionCodeView = new TextView(mRootView.getContext()); TextView mAppSdkView = new TextView(mRootView.getContext()); TextView mAppSizeView = new TextView(mRootView.getContext()); setTextAppearance(mAppVersionNameView, tvAppSize); setTextAppearance(mAppVersionCodeView, tvAppSize); setTextAppearance(mAppSdkView, tvAppSize); setTextAppearance(mAppSizeView, tvAppSize); mAppVersionNameView.setGravity(Gravity.CENTER); mAppVersionCodeView.setGravity(Gravity.CENTER); mAppSdkView.setGravity(Gravity.CENTER); mAppSizeView.setGravity(Gravity.CENTER); String mAppVersionName; String mAppVersionCode; String mAppSdk; if (mAppInfo != null) { mAppVersionName = (String) XposedHelpers.callMethod(apkInfo, "getInstalledVersionName") + " ➟ " + mPkgInfo.versionName; mAppVersionCode = XposedHelpers.callMethod(apkInfo, "getInstalledVersionCode") + " ➟ " + mPkgInfo.getLongVersionCode(); mAppSdk = mAppInfo.minSdkVersion + "-" + mAppInfo.targetSdkVersion + " ➟ " + mPkgInfo.applicationInfo.minSdkVersion + "-" + mPkgInfo.applicationInfo.targetSdkVersion; } else { mAppVersionName = mPkgInfo.versionName; mAppVersionCode = String.valueOf(mPkgInfo.getLongVersionCode()); mAppSdk = mPkgInfo.applicationInfo.minSdkVersion + "-" + mPkgInfo.applicationInfo.targetSdkVersion; } mAppVersionNameView.setText(modRes.getString(R.string.various_install_app_info_version_name) + ": " + mAppVersionName); mAppVersionCodeView.setText(modRes.getString(R.string.various_install_app_info_version_code) + ": " + mAppVersionCode); mAppSdkView.setText(modRes.getString(R.string.various_install_app_info_sdk) + ": " + mAppSdk); mAppSizeView.setText(tvAppSize.getText()); linearLayout2.addView(mAppVersionNameView, 0); linearLayout2.addView(mAppVersionCodeView, 1); linearLayout2.addView(mAppSdkView, 2); linearLayout2.addView(mAppSizeView, 3); linearLayout.addView(mRoundImageView, 0); linearLayout.addView(mAppNameView, 1); linearLayout.addView(linearLayout2, 2); mRootView.addView(linearLayout); } }); } } private void setTextAppearance(TextView textView, TextView textView2) { textView.setTextSize(15f); textView.setTextColor(textView2.getTextColors()); textView.setEllipsize(TextUtils.TruncateAt.MARQUEE); textView.setHorizontalFadingEdgeEnabled(true); textView.setSingleLine(); textView.setMarqueeRepeatLimit(-1); textView.setSelected(true); textView.setHorizontallyScrolling(true); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/DisplayMoreApkInfoNew.kt ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller import android.annotation.SuppressLint import android.content.pm.ApplicationInfo import android.content.pm.PackageInfo import android.content.res.Configuration import android.content.res.Resources import android.text.TextUtils import android.view.Gravity import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import com.github.kyuubiran.ezxhelper.Log import com.sevtinge.cemiuiler.R import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DisplayUtils.dip2px import com.sevtinge.cemiuiler.utils.Helpers import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.callMethodOrNull import com.sevtinge.cemiuiler.utils.hookAfterMethod import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XposedHelpers import java.io.File import java.lang.reflect.Method import java.text.DecimalFormat import kotlin.math.roundToInt object DisplayMoreApkInfoNew : BaseHook() { private var mApkInfo: Class<*>? = null private var mAppInfoViewObject: Class<*>? = null private var mAppInfoViewObjectViewHolder: Class<*>? = null @SuppressLint("SetTextI18n") override fun init() { // if (!getBoolean("packageinstaller_show_more_apk_info", false)) return mApkInfo = findClassIfExists("com.miui.packageInstaller.model.ApkInfo")//.findClassOrNull() mAppInfoViewObject = findClassIfExists("com.miui.packageInstaller.ui.listcomponets.AppInfoViewObject")//.findClassOrNull() if (mAppInfoViewObject != null) { XposedLogUtils.logI("mAppInfoViewObject is $mAppInfoViewObject") mAppInfoViewObjectViewHolder = findClassIfExists("com.miui.packageInstaller.ui.listcomponets.AppInfoViewObject\$ViewHolder")//"com.miui.packageInstaller.ui.listcomponets.AppInfoViewObject\$ViewHolder".findClassOrNull() val methods: Array = XposedHelpers.findMethodsByExactParameters(mAppInfoViewObject, Void.TYPE, mAppInfoViewObjectViewHolder) if (methods.isNotEmpty()) { val fields = mAppInfoViewObject!!.declaredFields var apkInfoFieldName: String? = null for (field in fields) { if (mApkInfo!!.isAssignableFrom(field.type)) { apkInfoFieldName = field.name break } } if (apkInfoFieldName == null) return val finalApkInfoFieldName: String = apkInfoFieldName methods[0].hookAfterMethod { hookParam -> val viewHolder: Any = hookParam.args[0] ?: return@hookAfterMethod val mAppSizeTv = XposedHelpers.callMethod(viewHolder, "getAppSize") as TextView? ?: return@hookAfterMethod val mContext = mAppSizeTv.context val isDarkMode = mAppSizeTv.context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES val apkInfo: Any = XposedHelpers.getObjectField(hookParam.thisObject, finalApkInfoFieldName) val mAppInfo = apkInfo.callMethodOrNull("getInstalledPackageInfo") as ApplicationInfo? val mPkgInfo = apkInfo.callMethod("getPackageInfo") as PackageInfo val modRes = Helpers.getModuleRes(mAppSizeTv.context) as Resources val layout: LinearLayout = mAppSizeTv.parent as LinearLayout layout.removeAllViews() val mContainerView = layout.parent as ViewGroup val mRoundImageView = mContainerView.getChildAt(0) as ImageView val mAppNameView = mContainerView.getChildAt(1) as TextView mContainerView.removeAllViews() val linearLayout = LinearLayout(mContext) linearLayout.orientation = LinearLayout.VERTICAL linearLayout.gravity = Gravity.CENTER linearLayout.layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT ) val appNameViewParams: LinearLayout.LayoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT ) appNameViewParams.setMargins(0, dip2px(mContext, 10f), 0, 0) mAppNameView.layoutParams = appNameViewParams mAppNameView.gravity = Gravity.CENTER val linearLayout2 = LinearLayout(mContainerView.context) // val linearLayout2 = LinearLayout(mContext) linearLayout2.orientation = LinearLayout.VERTICAL linearLayout2.gravity = Gravity.CENTER linearLayout2.setPadding( dip2px(mContext, 18f), dip2px(mContext, 15f), dip2px(mContext, 18f), dip2px(mContext, 15f) ) linearLayout2.layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT ).also { it.setMargins(0, dip2px(mContext, 13f), 0, 0) } linearLayout2.background = modRes.getDrawable( if (isDarkMode) R.drawable.ic_packageinstaller_background_dark else R.drawable.ic_packageinstaller_background_light, modRes.newTheme() ) val mAppPackageNameView = TextView(mContext) mContainerView.removeAllViews() val mAppVersionNameView = TextView(mContainerView.context) val mAppVersionCodeView = TextView(mContainerView.context) val mAppSdkView = TextView(mContainerView.context) val mAppSizeView = TextView(mContainerView.context) setTextAppearance(mAppVersionNameView, mAppSizeTv) setTextAppearance(mAppVersionCodeView, mAppSizeTv) setTextAppearance(mAppSdkView, mAppSizeTv) setTextAppearance(mAppSizeView, mAppSizeTv) mAppPackageNameView.gravity = Gravity.CENTER mAppVersionNameView.gravity = Gravity.START mAppVersionCodeView.gravity = Gravity.START mAppSdkView.gravity = Gravity.START mAppSizeView.gravity = Gravity.START val mPackageName: String = mPkgInfo.applicationInfo.packageName val mAppVersionName: String val mAppVersionCode: String val mAppSdk: String var mOldAppSize = "" val newAppSize = apkInfo.callMethod("getFileSize") as Long val newAppSizeDistance = newAppSize.toFloat().roundToInt() / 1000000f val mNewAppSize = format(newAppSizeDistance) if (mAppInfo != null) { mAppVersionName = apkInfo.callMethod("getInstalledVersionName") as String + " ➟ " + mPkgInfo.versionName mAppVersionCode = apkInfo.callMethod("getInstalledVersionCode").toString() + " ➟ " + mPkgInfo.longVersionCode mAppSdk = mAppInfo.minSdkVersion.toString() + "-" + mAppInfo.targetSdkVersion + " ➟ " + mPkgInfo.applicationInfo.minSdkVersion + "-" + mPkgInfo.applicationInfo.targetSdkVersion val oldAppSize = Integer.valueOf(File(mAppInfo.sourceDir).length().toInt()) val oldAppSizeDistance = oldAppSize.toFloat().roundToInt() / 1000000f mOldAppSize = format(oldAppSizeDistance) + " ➟ " } else { mAppVersionName = mPkgInfo.versionName mAppVersionCode = mPkgInfo.longVersionCode.toString() mAppSdk = mPkgInfo.applicationInfo.minSdkVersion.toString() + "-" + mPkgInfo.applicationInfo.targetSdkVersion } mAppVersionNameView.text = modRes.getString(R.string.various_install_app_info_version_name) + ": " + mAppVersionName mAppVersionCodeView.text = modRes.getString(R.string.various_install_app_info_version_code) + ": " + mAppVersionCode mAppSdkView.text = modRes.getString(R.string.various_install_app_info_sdk) + ": " + mAppSdk mAppSizeView.text = modRes.getString(R.string.various_install_app_size) + ": " + mOldAppSize + mNewAppSize mAppPackageNameView.text = mPackageName linearLayout2.addView(mAppVersionNameView, 0) linearLayout2.addView(mAppVersionCodeView, 1) linearLayout2.addView(mAppSdkView, 2) linearLayout2.addView(mAppSizeView, 3) linearLayout.addView(mRoundImageView, 0) linearLayout.addView(mAppNameView, 1) linearLayout.addView(mAppPackageNameView, 2) linearLayout.addView(linearLayout2, 3) mContainerView.addView(linearLayout) } } } else { Log.ex("Cannot find appropriate method") } } } private fun setTextAppearance(textView: TextView, textView2: TextView) { textView.textSize = 17f textView.setTextColor(textView2.textColors) textView.ellipsize = TextUtils.TruncateAt.MARQUEE textView.isHorizontalFadingEdgeEnabled = true textView.setSingleLine() textView.marqueeRepeatLimit = -1 textView.isSelected = true textView.setHorizontallyScrolling(true) } private fun format(appSize: Float): String { val decimalFormat = DecimalFormat("0.00") return if (appSize >= 1024f) { decimalFormat.format(appSize / 1024f) + "GB" } else if (appSize >= 1.024f) { decimalFormat.format(appSize) + "MB" } else { decimalFormat.format(appSize * 1024f) + "KB" } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/InstallRiskDisable.kt ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object InstallRiskDisable : BaseHook() { override fun init() { /*val result = Objects.requireNonNull( mPackageInstallerResultMethodsMap!!["SecureVerifyEnable"] ) for (descriptor in result) { val mSecureVerifyEnable = descriptor.getMethodInstance(lpparam.classLoader) mSecureVerifyEnable.createHook { returnConstant(false) } } val result2 = Objects.requireNonNull( mPackageInstallerResultMethodsMap!!["isInstallRiskEnabled"] ) for (descriptor2 in result2) { val isInstallRiskEnabled = descriptor2.getMethodInstance(lpparam.classLoader) isInstallRiskEnabled.createHook { returnConstant(false) } } val result3 = Objects.requireNonNull( mPackageInstallerResultMethodsMap!!["DisableSafeModelTip"] ) for (descriptor in result3) { val mDisableSafeModelTip = descriptor.getMethodInstance(lpparam.classLoader) mDisableSafeModelTip.createHook { returnConstant(false) } }*/ dexKitBridge.findMethod { matcher { addUsingStringsEquals("secure_verify_enable") } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(false) } dexKitBridge.findMethod { matcher { addUsingStringsEquals("installerOpenSafetyModel") } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(false) } dexKitBridge.findMethod { matcher { addUsingStringsEquals("android.provider.MiuiSettings\$Ad") } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(false) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/InstallSource.java ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class InstallSource extends BaseHook { String mInstallSourcePackageName; @Override public void init() { mInstallSourcePackageName = mPrefsMap.getString("miui_package_installer_install_source", "com.android.fileexplorer"); findAndHookMethodSilently("com.miui.packageInstaller.InstallStart", "getCallingPackage", XC_MethodReplacement.returnConstant(mInstallSourcePackageName)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/MiuiPackageInstallModify.java ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class MiuiPackageInstallModify extends BaseHook { @Override public void init() { Class mCloudParams = findClassIfExists("com.miui.packageInstaller.model.CloudParams"); findAndHookConstructor(mCloudParams, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.setBooleanField(param.thisObject, "installNotAllow", false); XposedHelpers.setBooleanField(param.thisObject, "showSafeModeTip", false); XposedHelpers.setBooleanField(param.thisObject, "showAdsAfter", false); XposedHelpers.setBooleanField(param.thisObject, "showAdsBefore", false); XposedHelpers.setBooleanField(param.thisObject, "singletonAuthShowAdsAfter", true); XposedHelpers.setBooleanField(param.thisObject, "singletonAuthShowAdsBefore", false); XposedHelpers.setBooleanField(param.thisObject, "useSystemAppRules", true); XposedHelpers.setBooleanField(param.thisObject, "skipInstallConfirm", true); XposedHelpers.setBooleanField(param.thisObject, "allowHighLight", true); XposedHelpers.setBooleanField(param.thisObject, "openButton", true); XposedHelpers.setObjectField(param.thisObject, "safeType", "1"); } }); // 隐藏开启纯净模式提示 // SafeModeTipViewObject safeModeTipViewObject = new SafeModeTipViewObject(h10, pureModeElderTipViewObject.f5884m, null, null, 12, null); // safeModeTipViewObject.a(); a方法里的调用 findAndHookMethod("com.miui.packageInstaller.ui.listcomponets.g0", "a", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.setBooleanField(param.thisObject, "l", false); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/SafeMode.java ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class SafeMode extends BaseHook { @Override public void init() { findAndHookMethod("com.android.packageinstaller.compat.MiuiSettingsCompat", "isSafeModelEnable", Context.class, XC_MethodReplacement.returnConstant(mPrefsMap.getBoolean("miui_package_installer_safe_mode"))); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/packageinstaller/UpdateSystemApp.java ================================================ package com.sevtinge.cemiuiler.module.hook.packageinstaller; import android.content.pm.ApplicationInfo; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.lang.reflect.Method; import java.util.List; public class UpdateSystemApp extends BaseHook { Class mClz; @Override public void init() { findAndHookMethod("android.os.SystemProperties", "getBoolean", String.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { if ("persist.sys.allow_sys_app_update".equals(param.args[0])) { param.setResult(true); } } }); char letterClz = 'a'; for (int i = 0; i < 26; i++) { mClz = findClass("j2." + letterClz); if (mClz != null) { int length = mClz.getDeclaredMethods().length; if (length >= 15 && length <= 25) { List methods = List.of(mClz.getDeclaredMethods()); for (Method method : methods) { try { if (method.getParameterTypes()[0] == ApplicationInfo.class) { hookMethod(method, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(false); } }); break; } } catch (Throwable e) { e.printStackTrace(); } } break; } } letterClz = (char) (letterClz + 1); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/personalassistant/BlurOverlay.java ================================================ package com.sevtinge.cemiuiler.module.hook.personalassistant; import android.content.res.Configuration; import android.os.Build; import android.view.Window; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class BlurOverlay extends BaseHook { Class mDeviceAdapter; Class mPhoneDeviceAdapter; Class mFoldableDeviceAdapter; Class v; Window window; @Override public void init() { v = findClassIfExists("c.h.e.p.v"); Class mF = findClassIfExists("c.h.c.a.a.f"); mDeviceAdapter = findClassIfExists("com.miui.personalassistant.device.DeviceAdapter"); mPhoneDeviceAdapter = findClassIfExists("com.miui.personalassistant.device.PhoneDeviceAdapter"); mFoldableDeviceAdapter = findClassIfExists("com.miui.personalassistant.device.FoldableDeviceAdapter"); hookAllMethods(mDeviceAdapter, "create", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { if (v != null) { findAndHookMethod(v, "j", XC_MethodReplacement.returnConstant(true)); } } }); findAndHookMethod(mFoldableDeviceAdapter, "blurOverlayWindow", float.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { float f = (float) param.args[0]; if (f >= 0f) { hookAllConstructors(mF, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { window = (Window) XposedHelpers.getObjectField(param.thisObject, "b"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { window.setBackgroundBlurRadius((int) f); } } }); } } }); findAndHookMethod(mFoldableDeviceAdapter, "onConfigurationChanged", Configuration.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { /*Configuration configuration = (Configuration) param.args[0]; Configuration mConfiguration = (Configuration) XposedHelpers.getObjectField(param.thisObject, "mConfiguration"); Context mThemedContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mThemedContext"); if (mThemedContext instanceof ComponentCallbacks) { ((ComponentCallbacks) mThemedContext).onConfigurationChanged(configuration); } int updateFrom = mConfiguration.updateFrom(configuration); boolean z = (updateFrom & 128) != 0; boolean z2 = (updateFrom & 1024) != 0; if (z || z2) { Class mDensityScaleUtil = findClass("com.miui.personalassistant.device.DensityScaleUtil"); XposedHelpers.callStaticMethod(mDensityScaleUtil, "scaleHostDensity", mThemedContext, 0); } */ findAndHookMethod("com.miui.launcher.overlay.server.pane.SlidingPaneStateManager", "a", boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.args[0] = false; } }); int mCurrentBlurRadius = XposedHelpers.getIntField(param.thisObject, "mCurrentBlurRadius"); XposedHelpers.setIntField(param.thisObject, "mScreenSize", 5); XposedHelpers.setIntField(param.thisObject, "mCurrentBlurRadius", 100); XposedHelpers.callMethod(param.thisObject, "blurOverlayWindow", mCurrentBlurRadius); } }); findAndHookMethod(mFoldableDeviceAdapter, "onOpened", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { int mCurrentBlurRadius = XposedHelpers.getIntField(param.thisObject, "mCurrentBlurRadius"); if (Float.compare(mCurrentBlurRadius, 100f) != 0) { XposedHelpers.setIntField(param.thisObject, "mCurrentBlurRadius", 100); XposedHelpers.callMethod(param.thisObject, "blurOverlayWindow", mCurrentBlurRadius); } } }); findAndHookMethod(mFoldableDeviceAdapter, "onScroll", float.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { float f = (float) param.args[0]; int i = (int) ((f - 0.49f) * 204.08163f); int mCurrentBlurRadius = XposedHelpers.getIntField(param.thisObject, "mCurrentBlurRadius"); int i2 = mCurrentBlurRadius; if (i2 != i) { if (i2 <= 0 || i >= 0) { mCurrentBlurRadius = i; } else { mCurrentBlurRadius = 0; } XposedHelpers.callMethod(param.thisObject, "blurOverlayWindow", mCurrentBlurRadius); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/personalassistant/BlurPersonalAssistant.kt ================================================ package com.sevtinge.cemiuiler.module.hook.personalassistant import android.graphics.drawable.ColorDrawable import android.os.Build import android.view.Window import androidx.annotation.RequiresApi import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.api.BlurDraw import kotlin.math.abs object BlurPersonalAssistant : BaseHook() { private val blurRadius by lazy { mPrefsMap.getInt("personal_assistant_blurradius", 80) } private val backgroundColor by lazy { mPrefsMap.getInt("personal_assistant_color", -1) } @RequiresApi(Build.VERSION_CODES.S) override fun init() { // val appVersionName = Helpers.getPackageVersionName(lpparam) var lastBlurRadius = -1 /*val mScrollStateManager = mPersonalAssistantResultMethodsMap["ScrollStateManager"]!! for (descriptor in mScrollStateManager) { runCatching { val mScrollStateManagerMethod = descriptor.getMethodInstance(lpparam.classLoader) XposedLogUtils.logI("mScrollStateManager method is $mScrollStateManagerMethod") XposedBridge.hookMethod(mScrollStateManagerMethod, object : XC_MethodHook() { @RequiresApi(Build.VERSION_CODES.S) override fun afterHookedMethod(param: MethodHookParam) { val scrollX = param.args[0] as Float val window: Any? window = if(appVersionName.contains("FOR-DESIGNER")) { log("is designer ver.") HookUtils.getValueByField(param.thisObject, "e") ?: return } else { HookUtils.getValueByField(param.thisObject, "b") ?: return } if (window.javaClass.name.contains("Window")) { runCatching { window as Window val blurRadius = (scrollX * blurRadius).toInt() if (abs(blurRadius - lastBlurRadius) > 2) { window.setBackgroundBlurRadius(blurRadius) lastBlurRadius = blurRadius } val backgroundColorDrawable = ColorDrawable(backgroundColor) backgroundColorDrawable.alpha = (scrollX * 255).toInt() window.setBackgroundDrawable(backgroundColorDrawable) } } } }) } }*/ dexKitBridge.findMethod { matcher { addUsingStringsEquals("ScrollStateManager") } }.forEach { methodData -> methodData.getMethodInstance(lpparam.classLoader).createHook { after { val scrollX = it.args[0] as Float val fieldNames = ('a'..'z').map { name -> name.toString() } val window = BlurDraw.getValueByFields(it.thisObject, fieldNames) ?: return@after if (window.javaClass.name.contains("Window")) { runCatching { window as Window val blurRadius = (scrollX * blurRadius).toInt() if (abs(blurRadius - lastBlurRadius) > 2) { window.setBackgroundBlurRadius(blurRadius) lastBlurRadius = blurRadius } val backgroundColorDrawable = ColorDrawable(backgroundColor) backgroundColorDrawable.alpha = (scrollX * 255).toInt() window.setBackgroundDrawable(backgroundColorDrawable) } } } } } /* val AssistantOverlayWindowClass = findClassIfExists( "com.miui.personalassistant.core.overlay.AssistantOverlayWindow" ) ?: return XposedHelpers.findAndHookMethod( AssistantOverlayWindowClass, "a", Float::class.java, object : XC_MethodHook() { @RequiresApi(Build.VERSION_CODES.S) override fun afterHookedMethod(param: MethodHookParam) { val scrollX = param.args[0] as Float val window = HookUtils.getValueByField(param.thisObject, "b") ?: return if (window.javaClass.name.contains("Window")) { try { window as Window val blurRadius = (scrollX * blurRadius).toInt() if (abs(blurRadius - lastBlurRadius) > 2) { window.setBackgroundBlurRadius(blurRadius) lastBlurRadius = blurRadius } val backgroundColorDrawable = ColorDrawable(backgroundColor) backgroundColorDrawable.alpha = (scrollX * 255).toInt() window.setBackgroundDrawable(backgroundColorDrawable) } catch (e: Throwable) { // 重复报错会污染日志 // HookUtils.log(e.message) } } } }) */ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/personalassistant/BlurPersonalAssistantBackGround.kt ================================================ package com.sevtinge.cemiuiler.module.hook.personalassistant import android.content.res.Configuration import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.getIntField import com.sevtinge.cemiuiler.utils.hookBeforeAllMethods import com.sevtinge.cemiuiler.utils.hookBeforeMethod import com.sevtinge.cemiuiler.utils.new import com.sevtinge.cemiuiler.utils.replaceMethod import com.sevtinge.cemiuiler.utils.setObjectField object BlurPersonalAssistantBackGround : BaseHook() { private val deviceAdapter = loadClass("com.miui.personalassistant.device.DeviceAdapter") private val foldableDeviceAdapter by lazy { loadClass("com.miui.personalassistant.device.FoldableDeviceAdapter") } override fun init() { deviceAdapter.hookBeforeAllMethods("create") { it.result = foldableDeviceAdapter.new(it.args[0]) } try { foldableDeviceAdapter.hookBeforeMethod("onEnter", Boolean::class.java) { it.thisObject.setObjectField("mScreenSize", 3) } } catch (e: ClassNotFoundException) { foldableDeviceAdapter.hookBeforeMethod("onOpened") { it.thisObject.setObjectField("mScreenSize", 3) } } foldableDeviceAdapter.hookBeforeMethod("onConfigurationChanged", Configuration::class.java) { it.thisObject.setObjectField("mScreenSize", 3) } foldableDeviceAdapter.replaceMethod("onScroll", Float::class.java) { val f = it.args[0] as Float val i = (f * 100.0f).toInt() val mCurrentBlurRadius: Int = it.thisObject.getIntField("mCurrentBlurRadius") if (mCurrentBlurRadius != i) { if (mCurrentBlurRadius <= 0 || i >= 0) { it.thisObject.setObjectField("mCurrentBlurRadius", i) } else { it.thisObject.setObjectField("mCurrentBlurRadius", 0) } it.thisObject.callMethod("blurOverlayWindow", mCurrentBlurRadius) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/personalassistant/EnableFoldWidget.java ================================================ package com.sevtinge.cemiuiler.module.hook.personalassistant; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class EnableFoldWidget extends BaseHook { Class c; Class m2; Class ga; @Override public void init() { c = findClassIfExists("b.z.g"); m2 = findClassIfExists("c.h.e.i.b"); ga = findClassIfExists("c.h.e.p.ga"); findAndHookMethod(c, "a", Context.class, String.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { XposedHelpers.setStaticObjectField(m2, "a", "fold"); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/personalassistant/PadWidgetEnable.java ================================================ package com.sevtinge.cemiuiler.module.hook.personalassistant; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class PadWidgetEnable extends BaseHook { Class m = findClassIfExists("c.h.e.k.k.c.d"); Class m2 = findClassIfExists("c.h.e.p.s"); public enum DeviceType { PAD, FOLDABLE_DEVICE, PHONE } @Override public void init() { hookAllMethods(m2, "c", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { XposedHelpers.callMethod(XposedHelpers.findClassIfExists("miui.os.Build", lpparam.classLoader), "isTablet", true); XposedHelpers.setStaticBooleanField(XposedHelpers.findClassIfExists("miui.os.Build", lpparam.classLoader), "IS_TABLET", true); } }); /*findAndHookMethod(m,"a", Build.class, Context.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { findAndHookMethod(m2,"c", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { XposedHelpers.setStaticBooleanField(XposedHelpers.findClassIfExists("miui.os.Build",lpparam.classLoader),"IS_TABLET", true); } }); } });*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/personalassistant/WidgetCrack.kt ================================================ package com.sevtinge.cemiuiler.module.hook.personalassistant import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils class WidgetCrack : BaseHook() { override fun init() { try { loadClass("com.miui.maml.widget.edit.MamlutilKt").methodFinder().filterByName("themeManagerSupportPaidWidget").first().createHook { returnConstant(false) } loadClass("com.miui.personalassistant.picker.business.detail.PickerDetailViewModel").methodFinder().filterByName("isCanDirectAddMaMl").first() .createHook { returnConstant(true) } loadClass("com.miui.personalassistant.picker.business.detail.utils.PickerDetailDownloadManager\$Companion").methodFinder() .filterByName("isCanDownload").first().createHook { returnConstant(true) } loadClass("com.miui.personalassistant.picker.business.detail.utils.PickerDetailUtil").methodFinder().filterByName("isCanAutoDownloadMaMl").first() .createHook { returnConstant(true) } loadClass("com.miui.personalassistant.picker.business.detail.bean.PickerDetailResponse").methodFinder().filterByName("isPay").first().createHook { returnConstant(false) } loadClass("com.miui.personalassistant.picker.business.detail.bean.PickerDetailResponse").methodFinder().filterByName("isBought").first() .createHook { returnConstant(true) } loadClass("com.miui.personalassistant.picker.business.detail.bean.PickerDetailResponseWrapper").methodFinder().filterByName("isPay").first() .createHook { returnConstant(false) } loadClass("com.miui.personalassistant.picker.business.detail.bean.PickerDetailResponseWrapper").methodFinder().filterByName("isBought").first() .createHook { returnConstant(true) } loadClass("com.miui.personalassistant.picker.business.detail.PickerDetailViewModel").methodFinder().filterByName("shouldCheckMamlBoughtState") .first().createHook { returnConstant(false) } loadClass("com.miui.personalassistant.picker.business.detail.PickerDetailViewModel").methodFinder() .filterByName("isTargetPositionMamlPayAndDownloading").first().createHook { returnConstant(false) } loadClass("com.miui.personalassistant.picker.business.detail.PickerDetailViewModel").methodFinder() .filterByName("checkIsIndependentProcessWidgetForPosition").first().createHook { returnConstant(true) } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/phone/DualNrSupport.kt ================================================ package com.sevtinge.cemiuiler.module.hook.phone import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object DualNrSupport : BaseHook() { override fun init() { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isDualNrSupported" }.createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/phone/DualSaSupport.kt ================================================ package com.sevtinge.cemiuiler.module.hook.phone import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object DualSaSupport : BaseHook() { override fun init() { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isDualSaSupported" }.createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/phone/ModemFeature.kt ================================================ package com.sevtinge.cemiuiler.module.hook.phone import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object ModemFeature : BaseHook() { override fun init() { runCatching { loadClass("com.android.phone.FiveGManagerBase").methodFinder().first { name == "getModemFeatureMode" }.createHook { after { it.args[0] = -1 it.result = true } } } runCatching { loadClass("com.android.phone.MiuiPhoneUtils").methodFinder().first { name == "isModemFeatureSupported" }.createHook { after { it.args[0] = -1 } } } runCatching { loadClass("com.android.phone.MiuiPhoneUtils").methodFinder().first { name == "getModemFeatureFromDb" }.createHook { after { it.args[0] = -1 } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/phone/N1BandPhone.kt ================================================ package com.sevtinge.cemiuiler.module.hook.phone import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object N1BandPhone : BaseHook() { override fun init() { runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isN1Supported" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/phone/N28BandPhone.kt ================================================ package com.sevtinge.cemiuiler.module.hook.phone import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object N28BandPhone : BaseHook() { override fun init() { runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isN28Supported" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/phone/N5N8BandPhone.kt ================================================ package com.sevtinge.cemiuiler.module.hook.phone import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object N5N8BandPhone : BaseHook() { override fun init() { runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isN5Supported" }.createHook { returnConstant(true) } } runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isN8Supported" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/phone/ViceSlotVolteButton.kt ================================================ package com.sevtinge.cemiuiler.module.hook.phone import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.exec object ViceSlotVolteButton : BaseHook() { override fun init() { runCatching { exec("settings put global vice_slot_volte_data_enabled 1") loadClass("com.android.phone.MiuiPhoneUtils").methodFinder().first { name == "shouldHideViceSlotVolteDataButton" }.createHook { returnConstant(false) } } runCatching { loadClass("com.android.phone.MiuiPhoneUtils").methodFinder().first { name == "shouldHideSmartDualSimButton" }.createHook { returnConstant(false) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/powerkeeper/CustomRefreshRate.kt ================================================ package com.sevtinge.cemiuiler.module.hook.powerkeeper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.ObjectUtils import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object CustomRefreshRate : BaseHook() { override fun init() { /*val result1 = PowerKeeperDexKit.mPowerKeeperResultMethodsMap!!["fucSwitch"] result1!!.filter { it.isMethod }.map { it.getMethodInstance(EzXHelper.safeClassLoader).createHook { before { param -> ObjectUtils.setObject(param.thisObject, "mIsCustomFpsSwitch", "true") // setObject(param.thisObject, "fucSwitch", true) // val qwq = getObjectOrNull(param.thisObject, "mIsCustomFpsSwitch") // Log.i("hook mIsCustomFpsSwitch success, its:$qwq") } } }*/ dexKitBridge.findMethod { matcher { addUsingStringsEquals("custom_mode_switch", "fucSwitch") } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { before { ObjectUtils.setObject(it.thisObject, "mIsCustomFpsSwitch", "true") } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/powerkeeper/DontKillApps.kt ================================================ package com.sevtinge.cemiuiler.module.hook.powerkeeper import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object DontKillApps : BaseHook() { override fun init() { loadClass("miui.process.ProcessManager").methodFinder().first { name == "kill" }.createHook { returnConstant(false) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/powerkeeper/LockMaxFps.kt ================================================ package com.sevtinge.cemiuiler.module.hook.powerkeeper import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object LockMaxFps : BaseHook() { override fun init() { loadClass("com.miui.powerkeeper.statemachine.DisplayFrameSetting").methodFinder().first { name == "setScreenEffect" && parameterCount == 3 }.createHook { returnConstant(null) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/powerkeeper/PreventBatteryWitelist.java ================================================ package com.sevtinge.cemiuiler.module.hook.powerkeeper; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; public class PreventBatteryWitelist extends BaseHook { @Override public void init() { Helpers.hookAllMethods("com.miui.powerkeeper.utils.CommonAdapter", lpparam.classLoader, "addPowerSaveWhitelistApps", new MethodHook(20000) { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(null); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/scanner/EnableCard.java ================================================ package com.sevtinge.cemiuiler.module.hook.scanner; import com.sevtinge.cemiuiler.module.base.BaseHook; public class EnableCard extends BaseHook { @Override public void init() { hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isAddBusinessCard", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isBusinessCardModuleAvailable", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/scanner/EnableDocPpt.java ================================================ package com.sevtinge.cemiuiler.module.hook.scanner; import com.sevtinge.cemiuiler.module.base.BaseHook; public class EnableDocPpt extends BaseHook { @Override public void init() { hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isPPTModuleAvailable", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/scanner/EnableOcr.java ================================================ package com.sevtinge.cemiuiler.module.hook.scanner; import com.sevtinge.cemiuiler.module.base.BaseHook; public class EnableOcr extends BaseHook { @Override public void init() { hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isAddTextExtractionFunction", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/scanner/EnableTranslation.java ================================================ package com.sevtinge.cemiuiler.module.hook.scanner; import com.sevtinge.cemiuiler.module.base.BaseHook; public class EnableTranslation extends BaseHook { @Override public void init() { hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isAddTranslation", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isTranslationModuleAvailable", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/scanner/document/EnableDocument.java ================================================ package com.sevtinge.cemiuiler.module.hook.scanner.document; import com.sevtinge.cemiuiler.module.base.BaseHook; public class EnableDocument extends BaseHook { @Override public void init() { hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isAddDocumentModule", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/scanner/document/EnableExcel.java ================================================ package com.sevtinge.cemiuiler.module.hook.scanner.document; import com.sevtinge.cemiuiler.module.base.BaseHook; public class EnableExcel extends BaseHook { @Override public void init() { hookAllMethods("com.xiaomi.scanner.util.SPUtils", "getFormModule", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isSupportForm", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isAddFormRecognitionFunction", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/scanner/document/EnablePpt.java ================================================ package com.sevtinge.cemiuiler.module.hook.scanner.document; import com.sevtinge.cemiuiler.module.base.BaseHook; public class EnablePpt extends BaseHook { @Override public void init() { hookAllMethods("com.xiaomi.scanner.settings.FeatureManager", "isSupportPpt", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/screenrecorder/ForceSupportPlaybackCapture.kt ================================================ package com.sevtinge.cemiuiler.module.hook.screenrecorder import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers class ForceSupportPlaybackCapture : BaseHook() { override fun init() { // if (!xPrefs.getBoolean("force_support_playbackcapture", true)) return XposedHelpers.findAndHookMethod("android.os.SystemProperties", lpparam.classLoader, "getBoolean", String::class.java, Boolean::class.javaPrimitiveType, object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (param.args[0] == "ro.vendor.audio.playbackcapture.screen") param.result = true } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/screenrecorder/SaveToMovies.kt ================================================ package com.sevtinge.cemiuiler.module.hook.screenrecorder import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers object SaveToMovies : BaseHook() { override fun init() { val clazz = XposedHelpers.findClass("android.os.Environment", lpparam.classLoader) XposedHelpers.setStaticObjectField(clazz, "DIRECTORY_DCIM", "Movies") XposedHelpers.findAndHookMethod("android.content.ContentValues", lpparam.classLoader, "put", String::class.java, String::class.java, object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (param.args[0] == "relative_path") { param.args[1] = (param.args[1] as String).replace("DCIM", "Movies") } } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/screenrecorder/ScreenRecorderConfig.kt ================================================ package com.sevtinge.cemiuiler.module.hook.screenrecorder import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.isFinal object ScreenRecorderConfig : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals("Error when set frame value, maxValue = ") } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { before { param -> param.args[0] = 1200 param.args[1] = 1 param.method.declaringClass.declaredFields.firstOrNull { field -> field.also { it.isAccessible = true }.let { fieldAccessible -> fieldAccessible.isFinal && fieldAccessible.get(null).let { runCatching { (it as IntArray).contentEquals( intArrayOf(15, 24, 30, 48, 60, 90) ) }.getOrDefault(false) } } }?.set(null, intArrayOf(15, 24, 30, 48, 60, 90, 120, 144)) } } dexKitBridge.findMethod { matcher { addUsingStringsEquals("defaultBitRate = ") } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { before { param -> param.args[0] = 1200 param.args[1] = 1 param.method.declaringClass.declaredFields.firstOrNull { field -> field.also { it.isAccessible = true }.let { fieldAccessible -> fieldAccessible.isFinal && fieldAccessible.get(null).let { runCatching { (it as IntArray).contentEquals( intArrayOf(200, 100, 50, 32, 24, 16, 8, 6, 4, 1) ) }.getOrDefault(false) } } }?.set(null, intArrayOf(1200, 800, 400, 200, 100, 50, 32, 24, 16, 8, 6, 4, 1)) } } /* val mScreenRecorderConfigA = mScreenRecorderResultMethodsMap["ScreenRecorderConfigA"]!! assert(mScreenRecorderConfigA.size == 1) val mScreenRecorderConfigADescriptor = mScreenRecorderConfigA.first() val mScreenRecorderConfigAMethod: Method = mScreenRecorderConfigADescriptor.getMethodInstance(lpparam.classLoader) // XposedBridge.log("Cemiuiler: DeviceModify (Updater) dexkit method is $systemPropertiesMethod") mScreenRecorderConfigAMethod.createHook { before { param -> param.args[0] = 1200 param.args[1] = 1 param.method.declaringClass.declaredFields.firstOrNull { field -> field.also { it.isAccessible = true }.let { fieldAccessible -> fieldAccessible.isFinal && fieldAccessible.get(null).let { runCatching { (it as IntArray).contentEquals(intArrayOf(15, 24, 30, 48, 60, 90)) }.getOrDefault(false) } } }?.set(null, intArrayOf(15, 24, 30, 48, 60, 90, 120, 144)) } } val mScreenRecorderConfigB = mScreenRecorderResultMethodsMap["ScreenRecorderConfigB"]!! assert(mScreenRecorderConfigB.size == 1) val mScreenRecorderConfigBDescriptor = mScreenRecorderConfigB.first() val mScreenRecorderConfigBMethod: Method = mScreenRecorderConfigBDescriptor.getMethodInstance(lpparam.classLoader) // XposedBridge.log("Cemiuiler: DeviceModify (Updater) dexkit method is $systemPropertiesMethod") mScreenRecorderConfigBMethod.createHook { before { param -> param.args[0] = 1200 param.args[1] = 1 param.method.declaringClass.declaredFields.firstOrNull { field -> field.also { it.isAccessible = true }.let { fieldAccessible -> fieldAccessible.isFinal && fieldAccessible.get(null).let { runCatching { (it as IntArray).contentEquals(intArrayOf(200, 100, 50, 32, 24, 16, 8, 6, 4, 1)) }.getOrDefault(false) } } }?.set(null, intArrayOf(1200, 800, 400, 200, 100, 50, 32, 24, 16, 8, 6, 4, 1)) } }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/screenrecorder/UnlockMoreVolumeFrom.java ================================================ package com.sevtinge.cemiuiler.module.hook.screenrecorder; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class UnlockMoreVolumeFrom extends BaseHook { @Override public void init() { Class mVolumeFrom = findClassIfExists("w0.a"); findAndHookConstructor("w0.a", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.setStaticBooleanField(mVolumeFrom, "h", true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/screenshot/DeviceShellCustomize.kt ================================================ package com.sevtinge.cemiuiler.module.hook.screenshot import android.os.Build import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.ClassUtils.setStaticObject import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object DeviceShellCustomize : BaseHook() { private lateinit var device: String private val deviceS by lazy { mPrefsMap.getString("screenshot_device_customize", "") } override fun init() { loadClass("com.miui.gallery.editor.photo.screen.shell.res.ShellResourceFetcher").methodFinder() .filterByName("getResId") .first().createHook { before { if (!this@DeviceShellCustomize::device.isInitialized) { device = Build.DEVICE } setStaticObject(loadClass("android.os.Build"), "DEVICE", deviceS) } after { setStaticObject(loadClass("android.os.Build"), "DEVICE", device) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/screenshot/SaveToPictures.kt ================================================ package com.sevtinge.cemiuiler.module.hook.screenshot import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XposedHelpers object SaveToPictures : BaseHook() { override fun init() { val clazz = XposedHelpers.findClass("android.os.Environment", lpparam.classLoader) XposedHelpers.setStaticObjectField(clazz, "DIRECTORY_DCIM", "Pictures") } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/screenshot/UnlockMinimumCropLimit.kt ================================================ package com.sevtinge.cemiuiler.module.hook.screenshot import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import java.lang.reflect.Modifier object UnlockMinimumCropLimit : BaseHook() { private val mScreenCropViewMethod by lazy { dexKitBridge.findMethod { matcher { declaredClass { addUsingStringsEquals("fixImageBounds %f,%f") } usingNumbers(0.5f, 200) returnType = "int" modifiers = Modifier.PRIVATE } }.map { it.getMethodInstance(EzXHelper.classLoader) }.first() } override fun init() { mScreenCropViewMethod.createHook { returnConstant(0) } /*val mScreenCropView = findClassIfExists("com.miui.gallery.editor.photo.screen.crop.ScreenCropView\$h") returnIntConstant(mScreenCropView, "a")*/ } /*private fun returnIntConstant(cls: Class<*>?, methodName: String) { findAndHookMethod(cls, methodName, XC_MethodReplacement.returnConstant(0)) }*/ } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/screenshot/UnlockPrivacyMarking.kt ================================================ package com.sevtinge.cemiuiler.module.hook.screenshot import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object UnlockPrivacyMarking : BaseHook() { override fun init() { val isClass by lazy { loadClass("com.miui.gallery.editor.photo.screen.mosaic.ScreenMosaicView") } isClass.methodFinder().first { name == "isSupportPrivacyMarking" }.createHook { try { returnConstant(true) } catch (e: Exception) { XposedLogUtils.logW("UnSupport Privacy Marking") } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/AppLockPinScramble.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.ArrayList; import java.util.Collections; public class AppLockPinScramble extends BaseHook { @Override public void init() { hookAllConstructors("com.miui.applicationlock.widget.MiuiNumericInputView", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { LinearLayout keys = (LinearLayout) param.thisObject; ArrayList mRandomViews = new ArrayList<>(); View bottom0 = null; View bottom2 = null; for (int row = 0; row <= 3; row++) { ViewGroup cols = (ViewGroup) keys.getChildAt(row); for (int col = 0; col <= 2; col++) { if (row == 3) if (col == 0) { bottom0 = cols.getChildAt(col); continue; } else if (col == 2) { bottom2 = cols.getChildAt(col); continue; } mRandomViews.add(cols.getChildAt(col)); } cols.removeAllViews(); } Collections.shuffle(mRandomViews); int cnt = 0; for (int row = 0; row <= 3; row++) for (int col = 0; col <= 2; col++) { ViewGroup cols = (ViewGroup) keys.getChildAt(row); if (row == 3) if (col == 0) { cols.addView(bottom0); continue; } else if (col == 2) { cols.addView(bottom2); continue; } cols.addView(mRandomViews.get(cnt)); cnt++; } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/BlurSecurity.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter import android.content.Context import android.graphics.Color import android.graphics.ColorMatrixColorFilter import android.graphics.RenderEffect import android.graphics.drawable.LayerDrawable import android.graphics.drawable.VectorDrawable import android.os.Build import android.util.AttributeSet import android.view.View import android.view.ViewGroup import android.widget.ImageView import android.widget.ListView import android.widget.TextView import androidx.annotation.RequiresApi import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.ColorUtils import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.HookUtils import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import com.sevtinge.cemiuiler.utils.log.XposedLogUtils.logW import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers object BlurSecurity : BaseHook() { val blurRadius = mPrefsMap.getInt("security_center_blurradius", 60) val backgroundColor = mPrefsMap.getInt("security_center_color", -1) val shouldInvertColor = !ColorUtils.isDarkColor(backgroundColor) private var appVersionCode = 40000727 // 反色 同时保持红蓝色变化不大 @RequiresApi(Build.VERSION_CODES.S) val invertColorRenderEffect = RenderEffect.createColorFilterEffect( ColorMatrixColorFilter( floatArrayOf( 1f, 1f, -2f, 0f, 16f, 0f, 0f, 0f, 0f, 0f, -3f, 1f, 2f, 0f, 16f, 0f, 0f, 0f, 0.85f, 0f ) ) ) // 不反转颜色的名单ID或类名 // whiteList 不在列表内子元素也会反色 private val invertColorWhiteList = arrayOf("lv_main", "second_view") // keepList 列表内元素及其子元素不会反色 private val keepColorList = arrayOf("rv_information") override fun init() { // if (getPackageVersionCode(lpparam) >= 40000790) return //暂时屏蔽高版本启用模糊,待修复后移除 //我觉得更像是傻逼miui的反色炸了 val turboLayoutClass = findClassIfExists( "com.miui.gamebooster.windowmanager.newbox.TurboLayout" ) ?: return val newToolBoxTopViewClass = findClassIfExists( "com.miui.gamebooster.windowmanager.newbox.NewToolBoxTopView" ) ?: return var newBoxClass: Class<*>? = null turboLayoutClass.methods.forEach { if (it.name == "getDockLayout") { newBoxClass = it.returnType } } if (newBoxClass == null) { return } XposedBridge.hookAllConstructors(newBoxClass, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val view = param.thisObject as View view.addOnAttachStateChangeListener( object : View.OnAttachStateChangeListener { @RequiresApi(Build.VERSION_CODES.S) override fun onViewAttachedToWindow(view: View) { // 已有背景 避免重复添加 if (view.background != null) { if (HookUtils.isBlurDrawable(view.background)) { return } } view.background = HookUtils.createBlurDrawable(view, blurRadius, 40, backgroundColor) } override fun onViewDetachedFromWindow(view: View) { view.background = null } }) } }) XposedBridge.hookAllConstructors(newToolBoxTopViewClass, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val view = param.thisObject as View view.addOnAttachStateChangeListener( object : View.OnAttachStateChangeListener { @RequiresApi(Build.VERSION_CODES.S) override fun onViewAttachedToWindow(view: View) { val viewPaernt = view.parent as ViewGroup val gameContentLayout = viewPaernt.parent as ViewGroup if (gameContentLayout.background != null) { if (HookUtils.isBlurDrawable(gameContentLayout.background)) { return } } gameContentLayout.background = HookUtils.createBlurDrawable(gameContentLayout, blurRadius, 40, backgroundColor) if (shouldInvertColor) { invertViewColor(gameContentLayout) // 设置 RenderEffect 后会导致文字动画出现问题,故去除动画 val performanceTextView = XposedHelpers.callMethod( param.thisObject, "getPerformanceTextView" ) as View XposedHelpers.findAndHookMethod( performanceTextView.javaClass, if (appVersionCode >= 40000749) "e" else "a", Boolean::class.java, object : XC_MethodReplacement() { override fun replaceHookedMethod(param: MethodHookParam?) { param?.result = null } }) } var headBackground = HookUtils.getValueByField(param.thisObject, "j") if (headBackground == null) { headBackground = HookUtils.getValueByField(param.thisObject, "j") } else if (!headBackground.javaClass.name.contains("ImageView")) { headBackground = HookUtils.getValueByField(param.thisObject, "C") } if (headBackground == null) { return } if (headBackground.javaClass.name.contains("ImageView")) { headBackground as ImageView headBackground.visibility = View.GONE } } override fun onViewDetachedFromWindow(view: View) { val viewPaernt = view.parent as ViewGroup val gameContentLayout = viewPaernt.parent as ViewGroup gameContentLayout.background = null } }) } }) // if (getPackageVersionCode(lpparam) >= 40000754) { dexKitBridge.findMethod { matcher { returnType = "android.view.View" paramTypes = listOf("android.content.Context", "boolean", "boolean") } /* methodReturnType = "Landroid/view/View;" methodParamTypes = arrayOf("Landroid/content/Context;", "Z", "Z")*/ }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { after { param -> val mainContent = HookUtils.getValueByField(param.thisObject, "b") as ViewGroup mainContent.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener { @RequiresApi(Build.VERSION_CODES.S) override fun onViewAttachedToWindow(view: View) { if (view.background != null) { if (HookUtils.isBlurDrawable(view.background)) return } view.background = HookUtils.createBlurDrawable(view, blurRadius, 40, backgroundColor) if (shouldInvertColor) invertViewColor(mainContent) } override fun onViewDetachedFromWindow(view: View) { view.background = null } }) } } /* XposedHelpers.findAndHookMethod( videoBoxViewClass, videoBoxViewMethodName, Context::class.java, Boolean::class.java, Boolean::class.java, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val mainContent = HookUtils.getValueByField(param.thisObject, "b") as ViewGroup mainContent.addOnAttachStateChangeListener( object : View.OnAttachStateChangeListener { @RequiresApi(Build.VERSION_CODES.S) override fun onViewAttachedToWindow(view: View) { if (view.background != null) { if (HookUtils.isBlurDrawable(view.background)) { return } } view.background = HookUtils.createBlurDrawable(view, blurRadius, 40, backgroundColor) if (shouldInvertColor) { invertViewColor(mainContent) } } override fun onViewDetachedFromWindow(view: View) { view.background = null } }) } }) } else { XposedHelpers.findAndHookMethod( videoBoxViewClass, videoBoxViewMethodName, Context::class.java, Boolean::class.java, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val mainContent = HookUtils.getValueByField(param.thisObject, "b") as ViewGroup mainContent.addOnAttachStateChangeListener( object : View.OnAttachStateChangeListener { @RequiresApi(Build.VERSION_CODES.S) override fun onViewAttachedToWindow(view: View) { if (view.background != null) { if (HookUtils.isBlurDrawable(view.background)) { return } } view.background = HookUtils.createBlurDrawable(view, blurRadius, 40, backgroundColor) if (shouldInvertColor) { invertViewColor(mainContent) } } override fun onViewDetachedFromWindow(view: View) { view.background = null } }) } }) } */ if (shouldInvertColor) { val detailSettingsLayoutClass = findClassIfExists( "com.miui.gamebooster.videobox.view.DetailSettingsLayout" ) ?: return val srsLevelSeekBarProClass = findClassIfExists( "com.miui.gamebooster.videobox.view.SrsLevelSeekBarPro" ) ?: return var srsLevelSeekBarInnerViewClass = findClassIfExists( "com.miui.gamebooster.videobox.view.c" ) if (srsLevelSeekBarInnerViewClass == null) { srsLevelSeekBarInnerViewClass = findClassIfExists( "b8.c" ) ?: return } val videoBoxWhiteList = arrayOf( "miuix.slidingwidget.widget.SlidingButton", "android.widget.ImageView", "android.widget.CompoundButton", "com.miui.common.widgets.gif.GifImageView", "com.miui.gamebooster.videobox.view.SrsLevelSeekBar", "com.miui.gamebooster.videobox.view.SrsLevelSeekBarPro", "com.miui.gamebooster.videobox.view.VideoEffectImageView", "com.miui.gamebooster.videobox.view.DisplayStyleImageView", "com.miui.gamebooster.videobox.view.c", "b8.c", "com.miui.gamebooster.videobox.view.VBIndicatorView" ) val gameBoxWhiteList = arrayOf( "audition_view", "miuix.slidingwidget.widget.SlidingButton" ) val videoBoxKeepList = arrayOf("img_wrapper2") val gameBoxKeepList = arrayOf( "rl_header", "tv_barrage_color_pick", "seekbar_text_size", "seekbar_text_speed" ) var secondViewClass = findClassIfExists("com.miui.gamebooster.windowmanager.newbox.n") var secondViewMethodName = "b" if (appVersionCode >= 40000749) { secondViewClass = findClassIfExists( "com.miui.gamebooster.windowmanager.newbox.j" ) ?: return secondViewMethodName = "B" } val auditionViewClass = findClassIfExists("com.miui.gamebooster.customview.AuditionView") ?: return XposedBridge.hookAllMethods( detailSettingsLayoutClass, "setFunctionType", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val marqueeTextView = HookUtils.getValueByField(param.thisObject, "d") if (marqueeTextView != null) { marqueeTextView as TextView marqueeTextView.setTextColor(Color.GRAY) } val listView = HookUtils.getValueByField(param.thisObject, "c") as ListView val listViewAdapterClassName = listView.adapter.javaClass.name val listViewAdapterInnerClass = findClassIfExists("$listViewAdapterClassName\$a") ?: return XposedBridge.hookAllMethods( listViewAdapterInnerClass, "a", object : XC_MethodHook() { @RequiresApi(Build.VERSION_CODES.S) override fun afterHookedMethod(param: MethodHookParam) { val isSetupFunction = param.args[0].toString().contains("BaseModel") if (isSetupFunction) { listViewAdapterInnerClass.declaredFields.forEach { field -> val currentObject = field.get(param.thisObject) if (currentObject is ImageView) { if (getId(currentObject) == "img1" || getId( currentObject ) == "img2" ) { currentObject.setRenderEffect( RenderEffect.createColorFilterEffect( ColorMatrixColorFilter( floatArrayOf( 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f, 0f, 0f, 0.5f, 0.5f, 0.5f, 0f, 0f ) ) ) ) } } if (currentObject is View) { invertViewColor( currentObject, videoBoxWhiteList, videoBoxKeepList ) } } } } }) } }) XposedLogUtils.logI("3") XposedHelpers.findAndHookMethod( srsLevelSeekBarProClass, if (appVersionCode >= 40000749) "b" else "a", Context::class.java, AttributeSet::class.java, Int::class.java, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val bgColorField = srsLevelSeekBarProClass.getDeclaredField("j") bgColorField.isAccessible = true bgColorField.setInt( param.thisObject, ColorUtils.addAlphaForColor(Color.GRAY, 150) ) val selectTxtColorField = srsLevelSeekBarProClass.getDeclaredField("l") selectTxtColorField.isAccessible = true selectTxtColorField.setInt( param.thisObject, Color.WHITE ) val normalTxtColorField = srsLevelSeekBarProClass.getDeclaredField("l") normalTxtColorField.isAccessible = true normalTxtColorField.setInt( param.thisObject, Color.WHITE ) } } ) XposedHelpers.findAndHookMethod(srsLevelSeekBarInnerViewClass, "a", Context::class.java, AttributeSet::class.java, Int::class.java, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val bgColorField = srsLevelSeekBarInnerViewClass.getDeclaredField("h") bgColorField.isAccessible = true bgColorField.setInt( param.thisObject, ColorUtils.addAlphaForColor(Color.WHITE, 150) ) } } ) XposedHelpers.findAndHookMethod( secondViewClass, secondViewMethodName, View::class.java, object : XC_MethodHook() { @RequiresApi(Build.VERSION_CODES.S) override fun afterHookedMethod(param: MethodHookParam) { val view = param.args[0] as View invertViewColor(view, gameBoxWhiteList, gameBoxKeepList) } }) // 让图标颜色更深一点 XposedHelpers.findAndHookMethod( auditionViewClass, if (appVersionCode >= 40000749) "M" else "a", Context::class.java, object : XC_MethodHook() { @RequiresApi(Build.VERSION_CODES.S) override fun afterHookedMethod(param: MethodHookParam) { val view = HookUtils.getValueByField(param.thisObject, "d") as View val parentView = view.parent XposedLogUtils.logI(parentView.toString()) if (parentView is ViewGroup) { val lastChild = parentView.getChildAt(parentView.childCount - 1) if (lastChild is ImageView && lastChild.drawable is VectorDrawable) { val oldDrawable = lastChild.drawable val newDrawable = LayerDrawable( arrayOf( oldDrawable, oldDrawable, oldDrawable, oldDrawable, oldDrawable ) ) lastChild.setImageDrawable(newDrawable) } } invertViewColor(view, gameBoxWhiteList, gameBoxKeepList) } }) } XposedLogUtils.logI("4") } // 尽量给最外层加 RenderEffect 而不是 最内层 // whiteList 不在名单内的子视图依旧反转 // keepList 本身及子视图均不反转 @RequiresApi(Build.VERSION_CODES.S) fun invertViewColor( view: View, whiteList: Array = invertColorWhiteList, keepList: Array? = keepColorList, ) { if (keepList != null) { if (keepList.contains(getId(view))) { return } if (keepList.contains(view.javaClass.name)) { return } } try { if (isChildNeedInvertColor(view, whiteList, keepList)) { view.setRenderEffect(invertColorRenderEffect) } else { if (view is ViewGroup) { for (index in 0 until view.childCount) { val childView = view.getChildAt(index) if (childView != null) { invertViewColor(childView, whiteList, keepList) } } } } } catch (e: Throwable) { logW("$TAG => invertViewColor", e) } } private fun isChildNeedInvertColor( view: View, whiteList: Array, keepList: Array?, ): Boolean { val viewId = getId(view) if (whiteList.contains(viewId)) { return false } if (whiteList.contains(view.javaClass.name)) { return false } if (keepList != null) { if (keepList.contains(getId(view))) { return false } if (keepList.contains(view.javaClass.name)) { return false } } try { if (view is ViewGroup) { for (index in 0 until view.childCount) { val childView = view.getChildAt(index) if (childView != null) { if (!isChildNeedInvertColor(childView, whiteList, keepList)) { return false } } } } } catch (e: Throwable) { logW("$TAG => isChildNeedInvertColor", e) } return true } private fun getId(view: View): String { return if (view.id == View.NO_ID) "no-id" else view.resources.getResourceName(view.id) .replace("com.miui.securitycenter:id/", "") } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/DisableReport.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object DisableReport : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals("android.intent.action.VIEW", "com.xiaomi.market") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(false) } /* val result: List = java.util.Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultMap["IsShowReport"] ) for (descriptor in result) { val isShowReport: java.lang.reflect.Method = descriptor.getMethodInstance(lpparam.classLoader) log("isShowReport method is $isShowReport") if (isShowReport.returnType == Boolean::class.javaPrimitiveType) { XposedBridge.hookMethod( isShowReport, XC_MethodReplacement.returnConstant(false) ) } }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/GetBubbleAppString.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object GetBubbleAppString : BaseHook() { override fun init() { try { val classBubble = loadClass("com.miui.bubbles.Bubble") loadClass("com.miui.bubbles.settings.BubblesSettings").methodFinder().first { name == "getBubbleAppString" }.createHook { before { val stringBuilder = StringBuilder() val mActiveBubbles = it.thisObject.getObjectField("mActiveBubbles") for (bubble in mActiveBubbles as HashSet<*>) { stringBuilder.append( classBubble.getMethod("getPackageName").invoke(bubble) ) stringBuilder.append(":") stringBuilder.append(bubble.getObjectField("userId")) stringBuilder.append(",") } // XposedBridge.log("MaxFreeFormTest: getBubbleAppString called! Result:$stringBuilder") it.result = stringBuilder.toString() } } } catch (e: Throwable) { XposedLogUtils.logE(TAG, e) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/IsSbnBelongToActiveBubbleApp.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object IsSbnBelongToActiveBubbleApp : BaseHook() { override fun init() { runCatching { loadClass("com.miui.bubbles.settings.BubblesSettings").methodFinder().first { name == "isSbnBelongToActiveBubbleApp" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/NewBoxBlur.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.GradientDrawable; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import com.sevtinge.cemiuiler.utils.DisplayUtils; import de.robv.android.xposed.XposedHelpers; public class NewBoxBlur extends BaseHook { Class mNewBoxCls; Class mTurboaLayout; Class mWindowManager; Class mVideoBoxCls; Class mTurboLayout; Class mDockLayout; @Override public void init() { mDockLayout = findClassIfExists("com.miui.gamebooster.windowmanager.newbox.j"); mTurboLayout = findClassIfExists("com.miui.gamebooster.windowmanager.newbox.TurboLayout"); mNewBoxCls = findClassIfExists("com.miui.gamebooster.windowmanager.newbox.i"); mTurboaLayout = findClassIfExists("com.miui.gamebooster.windowmanager.newbox.NewToolBoxTopView"); mWindowManager = findClassIfExists("com.miui.gamebooster.windowmanager.j"); mVideoBoxCls = findClassIfExists("com.miui.gamebooster.videobox.adapter.i"); hookAllConstructors(mDockLayout, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ViewGroup view = (ViewGroup) param.thisObject; int paddingVertical = DisplayUtils.dip2px(view.getContext(), mPrefsMap.getInt("security_center_newbox_bg_padding_vertical", 10)); int paddingHorizontal = DisplayUtils.dip2px(view.getContext(), mPrefsMap.getInt("security_center_newbox_bg_padding_horizontal", 10)); view.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical); new BlurUtils(view, "security_center_newbox_bg_custom"); } }); // hookAllConstructors(mTurboLayout, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ViewGroup view = (ViewGroup) XposedHelpers.callMethod(param.thisObject, "getDockLayout"); new BlurUtils(view, "security_center_newbox_bg_custom"); } }); /*findAndHookConstructor(mNewBoxCls, Context.class, boolean.class, String.class, mWindowManager, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { View view = (View) param.thisObject; new BlurUtils(view, "various_new_box_blur"); } });*/ findAndHookMethod(mTurboaLayout, "a", boolean.class, boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ImageView view = (ImageView) XposedHelpers.getObjectField(param.thisObject, "j"); GradientDrawable shapeDrawable = new GradientDrawable(); shapeDrawable.setColor(Color.TRANSPARENT); view.setImageDrawable(shapeDrawable); } }); findAndHookMethod(mTurboaLayout, "onAttachedToWindow", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { View view = (View) param.thisObject; new BlurUtils(view, "security_center_newbox_bg_custom"); } }); findAndHookMethod(mVideoBoxCls, "a", Context.class, boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ViewGroup viewGroup = (ViewGroup) XposedHelpers.getObjectField(param.thisObject, "b"); new BlurUtils(viewGroup, "security_center_newbox_bg_custom"); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/RemoveConversationBubbleSettingsRestriction.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter import android.annotation.SuppressLint import android.content.Context import android.util.ArrayMap import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.getObjectField import org.lsposed.hiddenapibypass.HiddenApiBypass class RemoveConversationBubbleSettingsRestriction : BaseHook() { @SuppressLint("PrivateApi") override fun init() { loadClass("com.miui.bubbles.settings.BubblesSettings").methodFinder().first { name == "getDefaultBubbles" }.createHook { before { param -> val classBubbleApp = loadClass("com.miui.bubbles.settings.BubbleApp") val arrayMap = ArrayMap() val mContext = param.thisObject.getObjectField("mContext") as Context val mCurrentUserId = param.thisObject.getObjectField("mCurrentUserId") as Int val freeformSuggestionList = HiddenApiBypass.invoke( Class.forName("android.util.MiuiMultiWindowUtils"), null, "getFreeformSuggestionList", mContext ) as List<*> if (freeformSuggestionList.isNotEmpty()) { for (str in freeformSuggestionList) { val bubbleApp = classBubbleApp.getConstructor( String::class.java, Int::class.java ).newInstance(str, mCurrentUserId) classBubbleApp.getMethod("setChecked", Boolean::class.java) .invoke(bubbleApp, true) arrayMap[str as String] = bubbleApp } } param.result = arrayMap } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/RemoveOpenAppConfirmationPopup.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter import android.annotation.SuppressLint import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class RemoveOpenAppConfirmationPopup : BaseHook() { @SuppressLint("DiscouragedApi") override fun init() { loadClass("android.widget.TextView").methodFinder().first { name == "setText" && parameterTypes[0] == CharSequence::class.java }.createHook { after { val textView = it.thisObject as TextView if (it.args.isNotEmpty() && it.args[0]?.toString().equals( textView.context.resources.getString( textView.context.resources.getIdentifier( "button_text_accept", "string", textView.context.packageName ) ) ) ) { textView.performClick() } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/SidebarLineCustom.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.callbacks.XC_InitPackageResources object SidebarLineCustom : BaseHook() { override fun init() {} fun initResource(resParam: XC_InitPackageResources.InitPackageResourcesParam) { val mSidebarLineColorDefault = mPrefsMap.getInt("security_center_sidebar_line_color_default", -1294740525) val mSidebarLineColorDark = mPrefsMap.getInt("security_center_sidebar_line_color_dark", -6842473) val mSidebarLineColorLight = mPrefsMap.getInt("security_center_sidebar_line_color_light", -872415232) XposedLogUtils.logI("mSidebarLineColorDefault is $mSidebarLineColorDefault") XposedLogUtils.logI("mSidebarLineColorDark is $mSidebarLineColorDark") XposedLogUtils.logI("mSidebarLineColorLight is $mSidebarLineColorLight") resParam.res.setReplacement( "com.miui.securitycenter", "color", "sidebar_line_color", mSidebarLineColorDefault ) resParam.res.setReplacement( "com.miui.securitycenter", "color", "sidebar_line_color_dark", mSidebarLineColorLight ) resParam.res.setReplacement( "com.miui.securitycenter", "color", "sidebar_line_color_light", mSidebarLineColorDark ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/VideoDolbyOpen.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter; import androidx.annotation.NonNull; import com.github.kyuubiran.ezxhelper.HookFactory; import com.github.kyuubiran.ezxhelper.interfaces.IMethodHookCallback; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DexKit; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import org.luckypray.dexkit.query.FindMethod; import org.luckypray.dexkit.query.matchers.ClassMatcher; import org.luckypray.dexkit.query.matchers.MethodMatcher; import org.luckypray.dexkit.result.MethodData; import java.util.function.Consumer; import de.robv.android.xposed.XC_MethodHook; public class VideoDolbyOpen extends BaseHook { @Override public void init() { // try { // findClassIfExists("com.miui.gamebooster.service.DockWindowManagerService").getDeclaredMethod("N"); // findAndHookMethod("com.miui.gamebooster.service.DockWindowManagerService", "N", new MethodHook() { // @Override // protected void before(MethodHookParam param) { // XposedLogUtils.logI("Hook N"); // param.setResult(null); // } // }); // } catch (NoSuchMethodException e) { // XposedLogUtils.logI("Don't Find DockWindowManagerService$N"); // } // 查找类 // ClassData data = DexKit.INSTANCE.getDexKitBridge().findClass(FindClass.create() // .searchPackages("com.miui.gamebooster.service") // .matcher(ClassMatcher.create() // .className("com.miui.gamebooster.service.DockWindowManagerService") // ) // ).firstOrThrow(() -> new IllegalStateException("VideoDolbyOpen: No class found ClassData")); // // 类加入列表 // List list = Collections.singletonList(data); // 查找方法 MethodData methodData = DexKit.INSTANCE.getDexKitBridge().findMethod( FindMethod.create() .matcher(MethodMatcher.create() .declaredClass(ClassMatcher.create() .usingStrings("checkMiGamePermission error")) .usingStrings("dolby") ) ).firstOrThrow(() -> new IllegalStateException("VideoDolbyOpen: No class found MethodData")); // 执行Hook try { HookFactory.createMethodHook(methodData.getMethodInstance(lpparam.classLoader), new Consumer<>() { @Override public void accept(HookFactory hookFactory) { hookFactory.before( new IMethodHookCallback() { @Override public void onMethodHooked(@NonNull XC_MethodHook.MethodHookParam methodHookParam) { methodHookParam.setResult(null); } } ); } }); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "NoSuchMethodException: " + e); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/app/AppDefaultSort.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.app; import android.content.Context; import android.os.Bundle; import androidx.fragment.app.Fragment; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.PrefsUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.Field; import de.robv.android.xposed.XposedHelpers; public class AppDefaultSort extends BaseHook { Class mAppManagerCls; String fragCls = null; @Override public void init() { mAppManagerCls = findClassIfExists("com.miui.appmanager.AppManagerMainActivity"); findAndHookMethod(mAppManagerCls, "onCreate", Bundle.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.args[0] = checkBundle((Context) param.thisObject, (Bundle) param.args[0]); Class mFragXCls = findClassIfExists("androidx.fragment.app.Fragment"); Field[] fields = param.thisObject.getClass().getDeclaredFields(); for (Field field : fields) { if (Fragment.class.isAssignableFrom(field.getType()) || (mFragXCls != null && mFragXCls.isAssignableFrom(field.getType()))) { fragCls = field.getType().getCanonicalName(); break; } } if (fragCls != null) { hookAllMethods(fragCls, "onActivityCreated", new MethodHook() { @Override protected void before(final MethodHookParam param) throws Throwable { try { param.args[0] = checkBundle((Context) XposedHelpers.callMethod(param.thisObject, "getContext"), (Bundle) param.args[0]); } catch (Throwable t) { XposedLogUtils.logE("AppDefaultSortHook", "", t); } } }); } } }); } public static Bundle checkBundle(Context context, Bundle bundle) { if (context == null) { XposedLogUtils.logI("AppDefaultSort", "Context is null!"); return null; } if (bundle == null) bundle = new Bundle(); int order = Integer.parseInt(PrefsUtils.getSharedStringPrefs(context, "prefs_key_security_center_app_default_sort", "0")); bundle.putInt("current_sory_type", order - 1); bundle.putInt("current_sort_type", order - 1); return bundle; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/app/AppDetails.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.app; import android.annotation.SuppressLint; import android.app.Activity; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.res.Resources; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.UserHandle; import android.widget.Toast; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.XposedUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import de.robv.android.xposed.XposedHelpers; public class AppDetails extends BaseHook { Class mAmAppInfoCls; Class mFragmentCls; private Object mSupportFragment = null; private PackageInfo mLastPackageInfo; @Override public void init() { mAmAppInfoCls = findClassIfExists("com.miui.appmanager.AMAppInfomationActivity"); mFragmentCls = findClassIfExists("androidx.fragment.app.Fragment"); if (mAmAppInfoCls != null) { boolean oldMethodFound = false; for (Member method : mAmAppInfoCls.getDeclaredMethods()) { if ("onLoadFinished".equals(method.getName())) { oldMethodFound = true; } } if (mFragmentCls != null) { findAndHookConstructor(mFragmentCls, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Field piField = XposedHelpers.findFirstFieldByExactType(param.thisObject.getClass(), PackageInfo.class); if (piField != null) { mSupportFragment = param.thisObject; } } }); } if (!oldMethodFound) { findAndHookMethod(mAmAppInfoCls, "onCreate", Bundle.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Handler handler = new Handler(Looper.getMainLooper()); handler.post(() -> { final Activity act = (Activity) param.thisObject; Object contentFrag = act.getFragmentManager().findFragmentById(android.R.id.content); Object frag = contentFrag != null ? contentFrag : mSupportFragment; if (frag == null) { XposedLogUtils.logI(TAG, "Unable to find fragment"); return; } final Resources modRes; try { modRes = XposedUtils.getModuleRes(act); Field piField = XposedHelpers.findFirstFieldByExactType(frag.getClass(), PackageInfo.class); mLastPackageInfo = (PackageInfo) piField.get(frag); Method[] addPref = XposedHelpers.findMethodsByExactParameters(frag.getClass(), void.class, String.class, String.class, String.class); if (mLastPackageInfo == null || addPref.length == 0) { XposedLogUtils.logI(TAG, "Unable to find field/class/method in SecurityCenter to hook"); return; } else { addPref[0].setAccessible(true); } addPref[0].invoke(frag, "apk_versioncode", modRes.getString(R.string.app_details_apk_version_code), String.valueOf(mLastPackageInfo.versionCode)); addPref[0].invoke(frag, "app_uid", modRes.getString(R.string.app_details_app_uid), String.valueOf(mLastPackageInfo.applicationInfo.uid)); addPref[0].invoke(frag, "data_path", modRes.getString(R.string.app_details_data_path), mLastPackageInfo.applicationInfo.dataDir); addPref[0].invoke(frag, "apk_filename", modRes.getString(R.string.app_details_apk_file), mLastPackageInfo.applicationInfo.sourceDir); addPref[0].invoke(frag, "min_sdk", modRes.getString(R.string.app_details_min_sdk), String.valueOf(mLastPackageInfo.applicationInfo.minSdkVersion)); addPref[0].invoke(frag, "target_sdk", modRes.getString(R.string.app_details_sdk), String.valueOf(mLastPackageInfo.applicationInfo.targetSdkVersion)); handler.post(() -> { try { addPref[0].invoke(frag, "open_in_market", modRes.getString(R.string.app_details_playstore), ""); addPref[0].invoke(frag, "open_in_app", modRes.getString(R.string.app_details_launch), ""); } catch (Throwable t) { XposedLogUtils.logW(TAG, "1", t); } }); } catch (Throwable t) { XposedLogUtils.logW(TAG, "2", t); return; } hookAllMethods(frag.getClass(), "onPreferenceTreeClick", new MethodHook() { @SuppressLint("DiscouragedApi") @Override protected void before(MethodHookParam param1) throws Throwable { String key = (String) XposedHelpers.callMethod(param1.args[0], "getKey"); String title = (String) XposedHelpers.callMethod(param1.args[0], "getTitle"); switch (key) { case "apk_filename" -> { ((ClipboardManager) act.getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText(title, mLastPackageInfo.applicationInfo.sourceDir)); Toast.makeText(act, act.getResources().getIdentifier("app_manager_copy_pkg_to_clip", "string", act.getPackageName()), Toast.LENGTH_SHORT).show(); param1.setResult(true); } case "data_path" -> { ((ClipboardManager) act.getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText(title, mLastPackageInfo.applicationInfo.dataDir)); Toast.makeText(act, act.getResources().getIdentifier("app_manager_copy_pkg_to_clip", "string", act.getPackageName()), Toast.LENGTH_SHORT).show(); param1.setResult(true); } case "open_in_market" -> { try { Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + mLastPackageInfo.packageName)); launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); act.startActivity(launchIntent); } catch ( android.content.ActivityNotFoundException anfe) { Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + mLastPackageInfo.packageName)); launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); act.startActivity(launchIntent); } param1.setResult(true); } case "open_in_app" -> { Intent launchIntent = act.getPackageManager().getLaunchIntentForPackage(mLastPackageInfo.packageName); if (launchIntent == null) { Toast.makeText(act, modRes.getString(R.string.app_details_nolaunch), Toast.LENGTH_SHORT).show(); } else { int user = 0; try { int uid = act.getIntent().getIntExtra("am_app_uid", -1); user = (int) XposedHelpers.callStaticMethod(UserHandle.class, "getUserId", uid); } catch (Throwable t) { XposedLogUtils.logW(TAG, "3", t); } launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); if (user != 0) { try { XposedHelpers.callMethod(act, "startActivityAsUser", launchIntent, XposedHelpers.newInstance(UserHandle.class, user)); } catch (Throwable t) { XposedLogUtils.logW(TAG, "4", t); } } else { act.startActivity(launchIntent); } } param.setResult(true); } } } }); }); } }); } } else { XposedLogUtils.logI(TAG, "Cannot find activity class!"); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/app/AppDisable.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.app; import android.annotation.SuppressLint; import android.app.Activity; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Handler; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.XposedUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import de.robv.android.xposed.XposedHelpers; @SuppressLint("DiscouragedApi") public class AppDisable extends BaseHook { public ArrayList mMiuiCoreApps; @Override public void init() { findAndHookMethod("com.miui.appmanager.ApplicationsDetailsActivity", "onCreateOptionsMenu", Menu.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Activity act = (Activity) param.thisObject; Menu menu = (Menu) param.args[0]; MenuItem dis = menu.add(0, 666, 1, act.getResources().getIdentifier("app_manager_disable_text", "string", lpparam.packageName)); dis.setIcon(act.getResources().getIdentifier("action_button_stop_svg", "drawable", lpparam.packageName)); dis.setEnabled(true); dis.setShowAsAction(1); // XposedHelpers.setAdditionalInstanceField(param.thisObject, "mDisableButton", dis); PackageManager pm = act.getPackageManager(); Field piField = XposedHelpers.findFirstFieldByExactType(act.getClass(), PackageInfo.class); PackageInfo mPackageInfo = (PackageInfo) piField.get(act); ApplicationInfo appInfo = pm.getApplicationInfo(mPackageInfo.packageName, PackageManager.GET_META_DATA); boolean isSystem = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; boolean isUpdatedSystem = (appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; dis.setTitle(act.getResources().getIdentifier(appInfo.enabled ? "app_manager_disable_text" : "app_manager_enable_text", "string", lpparam.packageName)); mMiuiCoreApps = new ArrayList<>(Arrays.asList(act.getResources().getStringArray(R.array.miui_core_app_package_name))); if (mMiuiCoreApps.contains(mPackageInfo.packageName)) { dis.setEnabled(false); } if (!appInfo.enabled || (isSystem && !isUpdatedSystem)) { MenuItem item = menu.findItem(2); if (item != null) item.setVisible(false); } } }); findAndHookMethod("com.miui.appmanager.ApplicationsDetailsActivity", "onOptionsItemSelected", MenuItem.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { MenuItem item = (MenuItem) param.args[0]; if (item != null && item.getItemId() == 666) { Activity act = (Activity) param.thisObject; Resources modRes = XposedUtils.getModuleRes(act); Field piField = XposedHelpers.findFirstFieldByExactType(act.getClass(), PackageInfo.class); PackageInfo mPackageInfo = (PackageInfo) piField.get(act); if (mMiuiCoreApps.contains(mPackageInfo.packageName)) { Toast.makeText(act, modRes.getString(R.string.disable_app_settings), Toast.LENGTH_SHORT).show(); return; } PackageManager pm = act.getPackageManager(); ApplicationInfo appInfo = pm.getApplicationInfo(mPackageInfo.packageName, PackageManager.GET_META_DATA); boolean isSystem = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; int state = pm.getApplicationEnabledSetting(mPackageInfo.packageName); boolean isEnabledOrDefault = (state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT); if (isEnabledOrDefault) { if (isSystem) { /* String title = modRes.getString(R.string.disable_app_title); String text = modRes.getString(R.string.disable_app_text); new AlertDialog.Builder(act) .setTitle(title) .setMessage(text) .setPositiveButton(android.R.string.ok, (dialog, which) -> setAppState(act, mPackageInfo.packageName, item, false)) .setNegativeButton(android.R.string.cancel, null) .show();*/ setAppState(act, mPackageInfo.packageName, item, false); } else { setAppState(act, mPackageInfo.packageName, item, false); } } else { setAppState(act, mPackageInfo.packageName, item, true); } param.setResult(true); } } }); } private void setAppState(final Activity act, String pkgName, MenuItem item, boolean enable) { try { PackageManager pm = act.getPackageManager(); pm.setApplicationEnabledSetting(pkgName, enable ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0); int state = pm.getApplicationEnabledSetting(pkgName); boolean isEnabledOrDefault = (state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT); if ((enable && isEnabledOrDefault) || (!enable && !isEnabledOrDefault)) { item.setTitle(act.getResources().getIdentifier(enable ? "app_manager_disable_text" : "app_manager_enable_text", "string", "com.miui.securitycenter")); Toast.makeText(act, act.getResources().getIdentifier(enable ? "app_manager_enabled" : "app_manager_disabled", "string", "com.miui.securitycenter"), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(act, XposedUtils.getModuleRes(act).getString(R.string.disable_app_fail), Toast.LENGTH_LONG).show(); } new Handler().postDelayed(act::invalidateOptionsMenu, 500); } catch (Throwable t) { XposedLogUtils.logW(TAG, "", t); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/app/AppRestrict.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.app; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.Method; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class AppRestrict extends BaseHook { Class mAppManageUtils; @Override public void init() { mAppManageUtils = findClassIfExists("com.miui.appmanager.AppManageUtils"); Method[] mGetAppInfo = XposedHelpers.findMethodsByExactParameters(mAppManageUtils, ApplicationInfo.class, Object.class, PackageManager.class, String.class, int.class, int.class); if (mGetAppInfo.length == 0) { XposedLogUtils.logI(TAG, "Cannot find getAppInfo method!"); } else { hookMethod(mGetAppInfo[0], new MethodHook() { @Override protected void after(MethodHookParam param) { if ((int) param.args[3] == 128 && (int) param.args[4] == 0) { ApplicationInfo appInfo = (ApplicationInfo) param.getResult(); appInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; param.setResult(appInfo); } } }); } findAndHookMethod("com.miui.networkassistant.ui.fragment.ShowAppDetailFragment", "initFirewallData", new MethodHook() { @Override protected void before(MethodHookParam param) { Object mAppInfo = XposedHelpers.getObjectField(param.thisObject, "mAppInfo"); if (mAppInfo != null) XposedHelpers.setBooleanField(mAppInfo, "isSystemApp", false); } }); hookAllMethods("com.miui.networkassistant.service.FirewallService", "setSystemAppWifiRuleAllow", XC_MethodReplacement.DO_NOTHING); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/app/OpenByDefaultSetting.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.app import android.annotation.SuppressLint import android.app.Activity import android.content.Intent import android.content.pm.verify.domain.DomainVerificationManager import android.net.Uri import android.os.Build import android.view.View import androidx.annotation.RequiresApi import com.github.kyuubiran.ezxhelper.EzXHelper.appContext import com.sevtinge.cemiuiler.R import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers object OpenByDefaultSetting : BaseHook() { @RequiresApi(Build.VERSION_CODES.S) override fun init() { val domainVerificationManager: DomainVerificationManager by lazy { appContext.getSystemService( DomainVerificationManager::class.java ) } val defaultViewId = intArrayOf(-1) Helpers.findAndHookMethod( "com.miui.appmanager.ApplicationsDetailsActivity", lpparam.classLoader, "initView", object : MethodHook() { @SuppressLint("DiscouragedApi") @Throws(Throwable::class) override fun before(param: MethodHookParam) { if (defaultViewId[0] == -1) { val act = param.thisObject as Activity val pkgName = (param.thisObject as Activity).intent.getStringExtra("package_name")!! val isLinkHandlingAllowed = domainVerificationManager.getDomainVerificationUserState( pkgName )?.isLinkHandlingAllowed ?: false val subTextId = if (isLinkHandlingAllowed) R.string.app_link_open_always else R.string.app_link_open_never defaultViewId[0] = act.resources.getIdentifier( "am_detail_default", "id", "com.miui.securitycenter" ) mResHook.setResReplacement( "com.miui.securitycenter", "string", "app_manager_default_open_title", R.string.open_by_default ) mResHook.setResReplacement( "com.miui.securitycenter", "string", "app_manager_default_close_summary", subTextId ) mResHook.setResReplacement( "com.miui.securitycenter", "string", "app_manager_default_open_summary", subTextId ) } } }) Helpers.findAndHookMethod("com.miui.appmanager.ApplicationsDetailsActivity", lpparam.classLoader, "onClick", View::class.java, object : MethodHook() { @Throws(Throwable::class) override fun before(param: MethodHookParam) { val view = param.args[0] as View if (view.id == defaultViewId[0] && defaultViewId[0] != -1) { val act = param.thisObject as Activity val intent = Intent("android.settings.APP_OPEN_BY_DEFAULT_SETTINGS") val pkgName = act.intent.getStringExtra("package_name") intent.setData(Uri.parse("package:$pkgName")) act.startActivity(intent) param.setResult(null) } } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/battery/ScreenUsedTime.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.battery import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.Log import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object ScreenUsedTime : BaseHook() { private val cls by lazy { dexKitBridge.findClass { matcher { addUsingStringsEquals("not support screenPowerSplit", "PowerRankHelperHolder") } }.first().getInstance(EzXHelper.classLoader) } private val method1 by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("ishtar", "nuwa", "fuxi") } }.first().getMethodInstance(EzXHelper.classLoader) } private val method2 by lazy { dexKitBridge.findMethod { matcher { declaredClass = cls.name returnType = "boolean" // paramTypes = listOf() 2.0.0-rc3 已经修复此错误,可以使用 paramCount = 0 } }.map { it.getMethodInstance(EzXHelper.classLoader) }.toList() } override fun init() { Log.i("methods2 :$method2") method2.forEach { it.createHook { returnConstant( when (it) { method1 -> true else -> false } ) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/battery/ShowBatteryTemperature.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.battery; import android.content.BroadcastReceiver; import android.content.Context; import android.content.IntentFilter; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Typeface; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.DisplayUtils; import java.lang.reflect.Method; import de.robv.android.xposed.XposedHelpers; public class ShowBatteryTemperature extends BaseHook { Class mBatteryFragment; Class mBatteryFragment$a; @Override public void init() { mBatteryFragment = findClassIfExists("com.miui.powercenter.BatteryFragment", "com.miui.powercenter.a"); mBatteryFragment$a = findClassIfExists("com.miui.powercenter.BatteryFragment$a", "com.miui.powercenter.a$a"); Method[] methods = mBatteryFragment.getDeclaredMethods(); for (Method method : methods) { if (method.getReturnType() == String.class && method.getParameterCount() == 1) { hookMethod(method, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { String mBatteryTemperature = String.valueOf(getBatteryTemperature((Context) param.args[0])); param.setResult(mBatteryTemperature); } }); } } findAndHookMethod(mBatteryFragment$a, "run", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { View view = (View) XposedHelpers.getObjectField(param.thisObject, "a"); Context mContext = view.getContext(); boolean isDarkMode = (mContext.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; int currentTemperatureStateId = mContext.getResources().getIdentifier("current_temperature_state", "id", "com.miui.securitycenter"); TextView mTemperatureStateTv = view.findViewById(currentTemperatureStateId); applyTextView(mContext, mTemperatureStateTv); RelativeLayout mContainerView = (RelativeLayout) mTemperatureStateTv.getParent(); mContainerView.removeView(mTemperatureStateTv); TextView mTemperatureUnit = new TextView(mContext); applyTemperatureStyle(mContext, mTemperatureUnit, isDarkMode); LinearLayout mTemperature = new LinearLayout(mContext); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, mContainerView.getId()); params.setMargins(0, 0, 0, DisplayUtils.dip2px(mContext, 21.5f)); mTemperature.setLayoutParams(params); mTemperature.addView(mTemperatureStateTv); mTemperature.addView(mTemperatureUnit); mContainerView.addView(mTemperature); } }); } private void applyTextView(Context context, TextView tv) { LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); tv.setLayoutParams(lp); tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 34.6f); tv.setGravity(Gravity.BOTTOM); tv.setIncludeFontPadding(false); tv.setTypeface(Typeface.create(null, 500, false)); } private void applyTemperatureStyle(Context context, TextView tv, boolean isDarkMode) { LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); lp.setMargins(DisplayUtils.dip2px(context, 3), 0, 0, 0); tv.setLayoutParams(lp); tv.setText("℃"); tv.setTextColor(Color.parseColor(isDarkMode ? "#e6e6e6" : "#333333")); tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); tv.setGravity(Gravity.BOTTOM); tv.setTypeface(Typeface.create(null, 700, false)); tv.setHeight((int) 49f); tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START); } private int getBatteryTemperature(Context context) { return context.registerReceiver((BroadcastReceiver) null, new IntentFilter("android.intent.action.BATTERY_CHANGED")).getIntExtra("temperature", 0) / 10; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/battery/ShowBatteryTemperatureNew.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.battery import android.annotation.SuppressLint import android.app.AndroidAppHelper import android.content.BroadcastReceiver import android.content.Context import android.content.IntentFilter import android.content.res.Configuration import android.graphics.Color import android.graphics.Typeface import android.util.TypedValue import android.view.Gravity import android.view.View import android.widget.LinearLayout import android.widget.RelativeLayout import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.MemberExtensions.paramCount import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DisplayUtils.dip2px import com.sevtinge.cemiuiler.utils.findClassOrNull import com.sevtinge.cemiuiler.utils.getObjectFieldAs import com.sevtinge.cemiuiler.utils.isStatic object ShowBatteryTemperatureNew : BaseHook() { @SuppressLint("DiscouragedApi") override fun init() { // if (!getBoolean("securitycenter_show_battery_temperature", false)) return val batteryFragmentClass = "com.miui.powercenter.BatteryFragment".findClassOrNull() if (batteryFragmentClass != null) { loadClass("com.miui.powercenter.BatteryFragment").methodFinder().first { paramCount == 1 && returnType == String::class.java && isStatic } } else { loadClass("com.miui.powercenter.a").methodFinder().first { paramCount == 1 && returnType == String::class.java && isStatic } }.createHook { after { it.result = getBatteryTemperature(it.args[0] as Context).toString() } } if (batteryFragmentClass != null) { loadClass("com.miui.powercenter.BatteryFragment\$a").methodFinder().first { name == "run" } } else { loadClass("com.miui.powercenter.a\$a").methodFinder().first { name == "run" } }.createHook { after { hookParam -> val context = AndroidAppHelper.currentApplication().applicationContext val isDarkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES val currentTemperatureState = context.resources.getIdentifier("current_temperature_state", "id", "com.miui.securitycenter") val view = hookParam.thisObject.getObjectFieldAs("a") val textView = view.findViewById(currentTemperatureState) textView.apply { when (layoutParams) { is LinearLayout.LayoutParams -> { (layoutParams as LinearLayout.LayoutParams).topMargin = 0 setPadding(0, dip2px(context, 4f), 0, 0) height = dip2px(context, 49f) } } setTextSize(TypedValue.COMPLEX_UNIT_DIP, 36.4f) gravity = Gravity.NO_GRAVITY typeface = Typeface.create(null, 700, false) textAlignment = View.TEXT_ALIGNMENT_VIEW_START } val temperatureContainer = context.resources.getIdentifier("temperature_container", "id", "com.miui.securitycenter") when (val childView = view.findViewById(temperatureContainer).getChildAt(1)) { is LinearLayout -> { childView.orientation = LinearLayout.VERTICAL val l1 = childView.getChildAt(0) val l2 = childView.getChildAt(1) val linearLayout = LinearLayout(context) val linearLayout1 = LinearLayout(context).apply { orientation = LinearLayout.HORIZONTAL } val tempView = TextView(context).apply { layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT ) (layoutParams as LinearLayout.LayoutParams).marginStart = dip2px(context, 3.6f) setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13.1f) setTextColor(Color.parseColor(if (isDarkMode) "#e6e6e6" else "#333333")) setPadding(0, dip2px(context, 26f), 0, 0) text = "℃" gravity = Gravity.NO_GRAVITY typeface = Typeface.create(null, 700, false) textAlignment = View.TEXT_ALIGNMENT_VIEW_START } childView.removeAllViews() linearLayout.addView(l1) linearLayout1.addView(l2) linearLayout1.addView(tempView) childView.addView(linearLayout) childView.addView(linearLayout1) } is RelativeLayout -> { val relativeLayout = RelativeLayout(context) val l1 = childView.getChildAt(0) val l2 = childView.getChildAt(1).apply { layoutParams = RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT ).also { it.addRule(RelativeLayout.BELOW, l1.id) it.addRule(RelativeLayout.ALIGN_START, l1.id) } (layoutParams as RelativeLayout.LayoutParams).topMargin = -dip2px(context, 0.78f) } val tempView = TextView(context).apply { layoutParams = RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT ).also { it.addRule(RelativeLayout.END_OF, l2.id) it.addRule(RelativeLayout.ALIGN_BOTTOM, l2.id) } setPadding(dip2px(context, 3.6f), 0, 0, dip2px(context, 5.9f)) setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13.1f) setTextColor(Color.parseColor(if (isDarkMode) "#e6e6e6" else "#333333")) text = "℃" gravity = Gravity.NO_GRAVITY typeface = Typeface.create(null, 700, false) textAlignment = View.TEXT_ALIGNMENT_VIEW_START } childView.removeAllViews() relativeLayout.addView(l1) relativeLayout.addView(l2) relativeLayout.addView(tempView) childView.addView(relativeLayout) } } } } } private fun getBatteryTemperature(context: Context): Int { return context.registerReceiver( null as BroadcastReceiver?, IntentFilter("android.intent.action.BATTERY_CHANGED") )!! .getIntExtra("temperature", 0) / 10 } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/battery/UnlockSmartCharge.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.battery import com.github.kyuubiran.ezxhelper.ClassLoaderProvider.classLoader import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object UnlockSmartCharge : BaseHook() { private val smartChg by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("persist.vendor.smartchg") } }.map { it.getMethodInstance(classLoader) }.toList() } override fun init() { smartChg.createHooks { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/battery/UnlockSuperWirelessCharge.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.battery import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object UnlockSuperWirelessCharge : BaseHook() { private val superWirelessCharge by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("persist.vendor.tx.speed.control") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(EzXHelper.classLoader) } private val superWirelessChargeTip by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("key_is_connected_super_wls_tx") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(EzXHelper.classLoader) } override fun init() { superWirelessCharge?.createHook { returnConstant(true) } superWirelessChargeTip?.createHook { returnConstant(true) } /*try { val result: List = java.util.Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultMap["SuperWirelessCharge"] ) for (descriptor in result) { val SuperWirelessCharge: java.lang.reflect.Method = descriptor.getMethodInstance(lpparam.classLoader) log("SuperWirelessCharge method is $SuperWirelessCharge") if (SuperWirelessCharge.returnType == Boolean::class.javaPrimitiveType) { XposedBridge.hookMethod( SuperWirelessCharge, XC_MethodReplacement.returnConstant(true) ) } } } catch (e: Throwable) { e.printStackTrace() } try { val result: List = java.util.Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultMap["SuperWirelessChargeTip"] ) for (descriptor in result) { val SuperWirelessChargeTip: java.lang.reflect.Method = descriptor.getMethodInstance(lpparam.classLoader) log("SuperWirelessChargeTip method is $SuperWirelessChargeTip") if (SuperWirelessChargeTip.returnType == Boolean::class.javaPrimitiveType) { XposedBridge.hookMethod( SuperWirelessChargeTip, XC_MethodReplacement.returnConstant(true) ) } } } catch (e: Throwable) { e.printStackTrace() }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/beauty/BeautyFace.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.beauty import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import java.lang.reflect.Method object BeautyFace : BaseHook() { var beautyFace: Method? = null override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals("taoyao", "IN", "persist.vendor.vcb.ability") returnType = "boolean" } }.forEach { beautyFace = it.getMethodInstance(lpparam.classLoader) } beautyFace!!.createHook { returnConstant(true) } /*try { val result: List = Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultMap.get("BeautyFace") ) for (descriptor in result) { beautyFace = descriptor.getMethodInstance(lpparam.classLoader) log("beautyFace method is " + beautyFace) if (beautyFace!!.returnType == Boolean::class.javaPrimitiveType) { XposedBridge.hookMethod(beautyFace, XC_MethodReplacement.returnConstant(true)) } } } catch (e: Throwable) { e.printStackTrace() }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/beauty/BeautyLightAuto.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.beauty import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedBridge object BeautyLightAuto : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals("taoyao") returnType = "boolean" } }.forEach { if (!java.lang.String.valueOf(it).contains("")) { val beautyLightAuto: java.lang.reflect.Method = it.getMethodInstance(lpparam.classLoader) if (!java.lang.String.valueOf(it).contains(BeautyFace.beautyFace.toString())) { XposedLogUtils.logI("beautyLightAuto method is $beautyLightAuto") XposedBridge.hookMethod( beautyLightAuto, XC_MethodReplacement.returnConstant(true) ) } } } /*try { val result: List = java.util.Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultMap.get("BeautyLightAuto") ) for (descriptor in result) { if (!java.lang.String.valueOf(descriptor).contains("")) { val beautyLightAuto: java.lang.reflect.Method = descriptor.getMethodInstance(lpparam.classLoader) if (beautyLightAuto.returnType == Boolean::class.javaPrimitiveType && !java.lang.String.valueOf( descriptor ).contains(BeautyFace.beautyFace.toString()) ) { log("beautyLightAuto method is $beautyLightAuto") XposedBridge.hookMethod( beautyLightAuto, XC_MethodReplacement.returnConstant(true) ) } } } } catch (e: Throwable) { e.printStackTrace() }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/beauty/BeautyPc.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.beauty import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object BeautyPc : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals("persist.vendor.camera.facetracker.support") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(true) } /* try { val result: List = java.util.Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultMap.get("BeautyPc") ) for (descriptor in result) { val beautyPc: java.lang.reflect.Method = descriptor.getMethodInstance(lpparam.classLoader) log("beautyPc method is $beautyPc") if (beautyPc.returnType == Boolean::class.javaPrimitiveType) { XposedBridge.hookMethod(beautyPc, XC_MethodReplacement.returnConstant(true)) } } } catch (e: Throwable) { e.printStackTrace() }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/beauty/BeautyPrivacy.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.beauty import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object BeautyPrivacy : BaseHook() { private val privateCls by lazy { dexKitBridge.findClass { matcher { usingStrings = listOf("persist.sys.privacy_camera") } }.first().getInstance(EzXHelper.classLoader) } private val R0 by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("persist.sys.privacy_camera") } }.first().getMethodInstance(EzXHelper.classLoader) } private val invokeMethod by lazy { dexKitBridge.findMethod { matcher { declaredClass = privateCls.name paramTypes = emptyList() returnType = "boolean" addInvoke { returnType = R0.returnType.name paramTypes = listOf(R0.parameterTypes[0].name) declaredClass = privateCls.name } } }.map { it.getMethodInstance(EzXHelper.classLoader) }.toList() } override fun init() { R0.createHook { before { it.args[0] = true } } invokeMethod.createHooks { returnConstant(true) } /* try { val appVersionCode = Helpers.getPackageVersionCode(lpparam) val result = Objects.requireNonNull(SecurityCenterDexKit.mSecurityCenterResultClassMap["BeautyLight"]) for (descriptor in result) { val beautyPrivacyUtils = descriptor.getClassInstance(lpparam.classLoader) beautyPrivacyUtils.methodFinder().first { if (!IS_TABLET) { when { appVersionCode in 40000749..40000750 -> name == "X" appVersionCode in 40000754..40000756 -> name == "Q" appVersionCode in 40000761..40000762 -> name == "R" appVersionCode in 40000771..40000772 -> name == "X" appVersionCode in 40000774..40000799 || appVersionCode in 40000803..40000809 -> name == "Y" appVersionCode >= 40000800 -> name == "Z" // 手机端截止到 8.1.0-230721.0.1 版本 else -> name == "M" // 未混淆分类 } } else { when { appVersionCode == 40010749 -> name == "f" appVersionCode == 40010750 -> name == "l" appVersionCode == 40010771 -> name == "X" appVersionCode in 40010774..40010799 -> name == "Y" appVersionCode >= 40010800 -> name == "Z"// 平板端截止到 8.1.0-230721.0.1.pad 版本 else -> name == "l" // 未混淆分类 } } }.createHook { returnConstant(true) } } } catch (e: Exception) { log("BeautyPrivacy -> $e") }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/lab/AiClipboardEnable.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.lab import com.github.kyuubiran.ezxhelper.EzXHelper import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.module.hook.securitycenter.lab.LabUtilsClass.labUtilClass import com.sevtinge.cemiuiler.utils.Helpers import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object AiClipboardEnable : BaseHook() { private var labUtils: Class<*>? = null override fun init() { labUtilClass.forEach { labUtils = it.getInstance(EzXHelper.classLoader) XposedLogUtils.logI("labUtils class is $labUtils") findAndHookMethod( "com.miui.permcenter.settings.PrivacyLabActivity", "onCreateFragment", object : MethodHook() { override fun before(param: MethodHookParam) { val fm = Helpers.getStaticObjectFieldSilently(labUtils, "b") if (fm != null) { try { val featMap = fm as MutableMap featMap["mi_lab_ai_clipboard_enable"] = 0 // featMap.put("mi_lab_blur_location_enable", 0); } catch (ignore: Throwable) { } } } }) } /* try { val result: List = Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultClassMap.get("LabUtils") ) for (descriptor in result) { labUtils = descriptor.getClassInstance(lpparam.classLoader) log("labUtils class is $labUtils") findAndHookMethod( "com.miui.permcenter.settings.PrivacyLabActivity", "onCreateFragment", object : MethodHook() { protected override fun before(param: MethodHookParam) { val fm = Helpers.getStaticObjectFieldSilently(labUtils, "b") if (fm != null) { try { val featMap = fm as MutableMap featMap["mi_lab_ai_clipboard_enable"] = 0 // featMap.put("mi_lab_blur_location_enable", 0); } catch (ignore: Throwable) { } } } }) } } catch (e: Throwable) { e.printStackTrace() }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/lab/BlurLocationEnable.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.lab import com.github.kyuubiran.ezxhelper.EzXHelper import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.module.hook.securitycenter.lab.LabUtilsClass.labUtilClass import com.sevtinge.cemiuiler.utils.Helpers import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object BlurLocationEnable : BaseHook() { private var labUtils: Class<*>? = null override fun init() { labUtilClass.forEach { labUtils = it.getInstance(EzXHelper.classLoader) XposedLogUtils.logI("labUtils class is $labUtils") findAndHookMethod( "com.miui.permcenter.settings.PrivacyLabActivity", "onCreateFragment", object : MethodHook() { @Throws(Throwable::class) override fun before(param: MethodHookParam) { val fm = Helpers.getStaticObjectFieldSilently(labUtils, "b") if (fm != null) { try { val featMap = fm as MutableMap featMap["mi_lab_blur_location_enable"] = 0 // featMap.put("mi_lab_blur_location_enable", 0); } catch (ignore: Throwable) { } } } }) } /*try { val result: List = Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultClassMap.get("LabUtils") ) for (descriptor in result) { labUtils = descriptor.getClassInstance(lpparam.classLoader) log("labUtils class is $labUtils") findAndHookMethod( "com.miui.permcenter.settings.PrivacyLabActivity", "onCreateFragment", object : BaseHook.MethodHook() { @Throws(Throwable::class) protected override fun before(param: MethodHookParam) { val fm = Helpers.getStaticObjectFieldSilently(labUtils, "b") if (fm != null) { try { val featMap = fm as MutableMap featMap["mi_lab_blur_location_enable"] = 0 // featMap.put("mi_lab_blur_location_enable", 0); } catch (ignore: Throwable) { } } } }) } } catch (e: Throwable) { e.printStackTrace() }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/lab/GetNumberEnable.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.lab import com.github.kyuubiran.ezxhelper.EzXHelper import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.module.hook.securitycenter.lab.LabUtilsClass.labUtilClass import com.sevtinge.cemiuiler.utils.Helpers import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object GetNumberEnable : BaseHook() { private var labUtils: Class<*>? = null override fun init() { labUtilClass.forEach { labUtils = it.getInstance(EzXHelper.classLoader) XposedLogUtils.logI("labUtils class is $labUtils") findAndHookMethod( "com.miui.permcenter.settings.PrivacyLabActivity", "onCreateFragment", object : MethodHook() { @Throws(Throwable::class) override fun before(param: MethodHookParam) { val fm = Helpers.getStaticObjectFieldSilently(labUtils, "b") if (fm != null) { try { val featMap = fm as MutableMap featMap["mi_lab_operator_get_number_enable"] = 0 // featMap.put("mi_lab_blur_location_enable", 0); } catch (ignore: Throwable) { } } } }) } /* val result: List = Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultClassMap.get("LabUtils") ) for (descriptor in result) { labUtils = descriptor.getClassInstance(lpparam.classLoader) log("labUtils class is $labUtils") findAndHookMethod( "com.miui.permcenter.settings.PrivacyLabActivity", "onCreateFragment", object : BaseHook.MethodHook() { @Throws(Throwable::class) protected override fun before(param: MethodHookParam) { val fm = Helpers.getStaticObjectFieldSilently(labUtils, "b") if (fm != null) { try { val featMap = fm as MutableMap featMap["mi_lab_operator_get_number_enable"] = 0 // featMap.put("mi_lab_blur_location_enable", 0); } catch (ignore: Throwable) { } } } }) } } catch (e: Throwable) { e.printStackTrace() }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/lab/LabUtilsClass.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.lab import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object LabUtilsClass { val labUtilClass by lazy { dexKitBridge.findClass { matcher { addUsingStringsEquals("mi_lab_ai_clipboard_enable", "mi_lab_blur_location_enable") } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/other/DisableRootCheck.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.other import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object DisableRootCheck : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals("key_check_item_root") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { returnConstant(false) } /*try { val result: List = Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultMap["rootCheck"] ) for (descriptor in result) { val checkIsRooted: Method = descriptor.getMethodInstance(lpparam.classLoader) if (checkIsRooted.returnType == Boolean::class.javaPrimitiveType) { XposedBridge.hookMethod( checkIsRooted, XC_MethodReplacement.returnConstant(false) ) } } } catch (e: Throwable) { e.printStackTrace() }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/other/FuckRiskPkg.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.other import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object FuckRiskPkg : BaseHook() { private val pkg by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals( "riskPkgList", "key_virus_pkg_list", "show_virus_notification" ) } }.map { it.getMethodInstance(EzXHelper.classLoader) }.toList() } override fun init() { pkg.createHooks { before { param -> param.result = null } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/other/LockOneHundredPoints.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.other import android.view.View import com.github.kyuubiran.ezxhelper.ClassLoaderProvider.classLoader import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import org.luckypray.dexkit.query.enums.StringMatchType object LockOneHundredPoints : BaseHook() { /* var mScoreManagerCls: Class<*>? = null var mMainContentFrameCls: Class<*>? = null override fun init() { mScoreManagerCls = findClassIfExists("com.miui.securityscan.scanner.ScoreManager") mMainContentFrameCls = findClassIfExists("com.miui.securityscan.ui.main.MainContentFrame") try { val result: List = Objects.requireNonNull>( SecurityCenterDexKit.mSecurityCenterResultMap.get("ScoreManager") ) for (descriptor in result) { val lockOneHundredPoints: Method = descriptor.getMethodInstance(lpparam.classLoader) log("lock 100 points method is $lockOneHundredPoints") if (lockOneHundredPoints.returnType == Int::class.javaPrimitiveType) { XposedBridge.hookMethod( lockOneHundredPoints, XC_MethodReplacement.returnConstant(0) ) } } } catch (e: Throwable) { e.printStackTrace() } *//*findAndHookMethod(mScoreManagerCls, "B", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { if(PrefsUtils.mSharedPreferences.getBoolean("prefs_key_security_center_score", false)) param.setResult(0); } });*//*findAndHookMethod( mMainContentFrameCls, "onClick", View::class.java, object : BaseHook.MethodHook() { @Throws(Throwable::class) protected override fun before(param: MethodHookParam) { if (PrefsUtils.mSharedPreferences.getBoolean( "prefs_key_security_center_score", false ) ) param.setResult(null) } }) }*/ private val score by lazy { dexKitBridge.findMethod { matcher { addUsingString("getMinusPredictScore", StringMatchType.Contains) } }.firstOrNull()?.getMethodInstance(classLoader) } override fun init() { loadClass("com.miui.securityscan.ui.main.MainContentFrame").methodFinder() .filterByName("onClick") .filterByParamTypes(View::class.java) .first().createHook { before { it.result = null } } score?.createHook { returnConstant(0) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/other/NoLowBatteryWarning.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.other import android.provider.Settings import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers object NoLowBatteryWarning : BaseHook() { override fun init() { val settingHook: MethodHook = object : MethodHook() { override fun before(param: MethodHookParam) { val key = param.args[1] as String if ("low_battery_dialog_disabled" == key) param.result = 1 else if ("low_battery_sound" == key) param.result = null } } Helpers.hookAllMethods(Settings.System::class.java, "getInt", settingHook) Helpers.hookAllMethods(Settings.Global::class.java, "getString", settingHook) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/other/SkipCountDownLimit.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.other; import android.os.Handler; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.lang.reflect.Method; import de.robv.android.xposed.XposedHelpers; public class SkipCountDownLimit extends BaseHook { Class mHandlerClass = null; Class mInterceptBaseFragmentCls; Class[] mInnerClasses; @Override public void init() { mInterceptBaseFragmentCls = findClassIfExists("com.miui.permcenter.privacymanager.InterceptBaseFragment"); mInnerClasses = mInterceptBaseFragmentCls.getDeclaredClasses(); findAndHookMethod("android.widget.TextView", "setEnabled", boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.args[0] = true; } }); for (Class mInnerClass : mInnerClasses) { if (Handler.class.isAssignableFrom(mInnerClass)) { mHandlerClass = mInnerClass; break; } } if (mHandlerClass != null) { hookAllConstructors(mHandlerClass, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { if (param.args.length == 2) { param.args[1] = 0; } } }); Method[] methods = XposedHelpers.findMethodsByExactParameters(mHandlerClass, void.class, int.class); if (methods.length > 0) { hookMethod(methods[0], new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.args[0] = 0; } }); } } /*findAndHookMethod("android.widget.TextView", "setText", CharSequence.class, TextView.BufferType.class, boolean.class, int.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Object[] mParam = param.args; String mText = param.args[0].toString(); if (mParam.length != 0 && mText.startsWith("确定(")) { param.args[0] = "确定"; } } });*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/sidebar/AddSideBarExpandReceiver.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; import android.view.MotionEvent; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.Method; import de.robv.android.xposed.XposedHelpers; public class AddSideBarExpandReceiver extends BaseHook { @Override public void init() { final boolean[] isHooked = {false, false}; boolean enableSideBar = mPrefsMap.getBoolean("security_center_leave_open"); if (!enableSideBar) { mResHook.setDensityReplacement("com.miui.securitycenter", "dimen", "sidebar_height_default", 8); mResHook.setDensityReplacement("com.miui.securitycenter", "dimen", "sidebar_height_vertical", 8); } Class RegionSamplingHelper = findClassIfExists("com.android.systemui.navigationbar.gestural.RegionSamplingHelper", lpparam.classLoader); if (RegionSamplingHelper == null) { XposedLogUtils.logI("failed to find RegionSamplingHelper"); } hookAllConstructors(RegionSamplingHelper, new MethodHook() { private int originDockLocation = -1; @Override protected void after(MethodHookParam param) throws Throwable { if (!isHooked[0]) { isHooked[0] = true; View view = (View) param.args[0]; if (originDockLocation == -1) { originDockLocation = view.getContext().getSharedPreferences("sp_video_box", 0).getInt("dock_line_location", 0);; } BroadcastReceiver showReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getBundleExtra("actionInfo"); int pos = originDockLocation; if (bundle != null) { pos = bundle.getInt("inDirection", 0); view.getContext().getSharedPreferences("sp_video_box", 0).edit().putInt("dock_line_location", pos).commit(); } showSideBar(view, pos); } }; view.getContext().registerReceiver(showReceiver, new IntentFilter(ACTION_PREFIX + "ShowSideBar")); XposedHelpers.setAdditionalInstanceField(param.thisObject, "showReceiver", showReceiver); if (!isHooked[1]) { isHooked[1] = true; Handler myhandler = new Handler(Looper.myLooper()); Runnable removeBg = new Runnable() { @Override public void run() { myhandler.removeCallbacks(this); if (!enableSideBar) { Object li = XposedHelpers.getObjectField(view, "mListenerInfo"); Object mOnTouchListener = XposedHelpers.getObjectField(li, "mOnTouchListener"); findAndHookMethod(mOnTouchListener.getClass(), "onTouch", View.class, MotionEvent.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { MotionEvent me = (MotionEvent) param.args[1]; if (me.getSource() != 9999) { param.setResult(false); } } }); } Class bgDrawable = view.getBackground().getClass(); findAndHookMethod(bgDrawable, "draw", Canvas.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(null); } }); view.setBackground(null); } }; myhandler.postDelayed(removeBg, 150); } } } }); findAndHookMethod(RegionSamplingHelper, "onViewDetachedFromWindow", android.view.View.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { isHooked[0] = false; BroadcastReceiver showReceiver = (BroadcastReceiver) XposedHelpers.getAdditionalInstanceField(param.thisObject, "showReceiver"); if (showReceiver != null) { View view = (View) param.args[0]; view.getContext().unregisterReceiver(showReceiver); XposedHelpers.removeAdditionalInstanceField(param.thisObject, "showReceiver"); } } }); Method[] methods = XposedHelpers.findMethodsByExactParameters(RegionSamplingHelper, void.class, Rect.class); if (methods.length == 0) { XposedLogUtils.logI("Cannot find appropriate start method"); return; } hookMethod(methods[0], new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(null); } }); } private static void showSideBar(View view, int dockLocation) { int[] location = new int[2]; view.getLocationOnScreen(location); int y = location[1]; long uptimeMillis = SystemClock.uptimeMillis(); MotionEvent downEvent, moveEvent, upEvent; if (dockLocation == 0) { // left downEvent = MotionEvent.obtain(uptimeMillis, uptimeMillis, MotionEvent.ACTION_DOWN, 4, y + 15, 0); moveEvent = MotionEvent.obtain(uptimeMillis, uptimeMillis + 20, MotionEvent.ACTION_MOVE, 160, y + 15, 0); upEvent = MotionEvent.obtain(uptimeMillis, uptimeMillis + 21, MotionEvent.ACTION_UP, 160, y + 15, 0); } else { int x = location[0]; downEvent = MotionEvent.obtain(uptimeMillis, uptimeMillis, MotionEvent.ACTION_DOWN, x - 4, y + 15, 0); moveEvent = MotionEvent.obtain(uptimeMillis, uptimeMillis + 20, MotionEvent.ACTION_MOVE, x - 160, y + 15, 0); upEvent = MotionEvent.obtain(uptimeMillis, uptimeMillis + 21, MotionEvent.ACTION_UP, x - 160, y + 15, 0); } downEvent.setSource(9999); moveEvent.setSource(9999); upEvent.setSource(9999); view.dispatchTouchEvent(downEvent); view.dispatchTouchEvent(moveEvent); view.dispatchTouchEvent(upEvent); downEvent.recycle(); moveEvent.recycle(); upEvent.recycle(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/sidebar/DisableDockSuggest.java ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.ArrayList; public class DisableDockSuggest extends BaseHook { @Override public void init() { MethodHook clearHook = new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { ArrayList blackList = new ArrayList(); blackList.add("xx.yy.zz"); int topMethod = 10; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement el: stackTrace) { if (el != null && topMethod < 20 && (el.getClassName().contains("edit.DockAppEditActivity") || el.getClassName().contains("BubblesSettings")) ) { return; } topMethod++; } param.setResult(blackList); } }; hookAllMethodsSilently("android.util.MiuiMultiWindowUtils", "getFreeformSuggestionList", clearHook); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/sidebar/game/RemoveMacroBlackList.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.game import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge class RemoveMacroBlackList : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { usingStrings = listOf("pref_gb_unsupport_macro_apps") paramTypes = listOf("java.util.ArrayList") returnType = "void" } }.first().getMethodInstance(EzXHelper.classLoader).createHook { before { it.result = ArrayList() } } dexKitBridge.findClass { matcher { usingStrings = listOf("com.netease.sky.mi") } }.first().getInstance(EzXHelper.classLoader).methodFinder() .filterByReturnType(Boolean::class.java) .filterByParamCount(1) .first().createHook { returnConstant(false) } dexKitBridge.findClass { matcher { usingStrings = listOf("content://com.xiaomi.macro.MacroStatusProvider/game_macro_change") } }.first().getInstance(EzXHelper.classLoader).methodFinder() .filterByReturnType(Boolean::class.java) .filterByParamCount(2) .first().createHook { returnConstant(true) } /*val macro = SecurityCenterDexKit.mSecurityCenterResultClassMap["Macro"]!! assert(macro.size == 1) val macroDescriptor = macro.first() val macroClass: Class<*> = macroDescriptor.getClassInstance(lpparam.classLoader) macroClass.methodFinder().first { returnType == Boolean::class.java && parameterCount == 1 }.createHook { returnConstant(false) } val macro1 = SecurityCenterDexKit.mSecurityCenterResultClassMap["Macro1"]!! assert(macro1.size == 1) val macro1Descriptor = macro1.first() val macro1Class: Class<*> = macro1Descriptor.getClassInstance(lpparam.classLoader) macro1Class.methodFinder().first { returnType == Boolean::class.java && parameterCount == 2 }.createHook { returnConstant(true) } val macro2 = SecurityCenterDexKit.mSecurityCenterResultMap["Macro2"]!! assert(macro2.isNotEmpty()) var macro2Descriptor = macro2[0] var macroMethod: Method = macro2Descriptor.getMethodInstance(lpparam.classLoader) if (macroMethod.returnType != ArrayList::class.java) { macro2Descriptor = macro2[1] macroMethod = macro2Descriptor.getMethodInstance(lpparam.classLoader) } macroMethod.createHook { before { it.result = ArrayList() } }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/sidebar/game/UnlockGunService.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.game import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object UnlockGunService : BaseHook() { override fun init() { dexKitBridge.findClass { matcher { usingStrings = listOf("gb_game_collimator_status") } }.map { val gbGameCollimatorClass = it.getInstance(EzXHelper.classLoader) dexKitBridge.findMethod { matcher { declaredClass = gbGameCollimatorClass.name returnType = "boolean" paramTypes = listOf("java.lang.String") } }.single().getMethodInstance(EzXHelper.classLoader).createHook { returnConstant(true) } } /*val gbGameCollimator = mSecurityCenterResultClassMap["GbGameCollimator"]!! assert(gbGameCollimator.size == 1) val gbGameCollimatorDescriptor = gbGameCollimator.first() val gbGameCollimatorClass: Class<*> = gbGameCollimatorDescriptor.getClassInstance(lpparam.classLoader) gbGameCollimatorClass.methodFinder().first { returnType == Boolean::class.java && parameterCount == 1 }.createHook { XposedLogUtils.logI("GunService class is $gbGameCollimatorClass") returnConstant(true) }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/sidebar/video/DisableRemoveScreenHoldOn.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.video import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object DisableRemoveScreenHoldOn : BaseHook() { /*override fun init() { try { val result: List = Objects.requireNonNull(SecurityCenterDexKit.mSecurityCenterResultMap.get("RemoveScreenHoldOn")) for (descriptor in result) { val removeScreenHoldOn: Method = descriptor.getMethodInstance(lpparam.classLoader) log("removeScreenHoldOn method is $removeScreenHoldOn") if (removeScreenHoldOn.returnType == Boolean::class.javaPrimitiveType) { XposedBridge.hookMethod( removeScreenHoldOn, XC_MethodReplacement.returnConstant(false) ) } } } catch (e: Throwable) { e.printStackTrace() } }*/ private val screen by lazy { dexKitBridge.findMethod { matcher { usingStrings = listOf("remove_screen_off_hold_on") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(EzXHelper.classLoader) } override fun init() { screen?.createHook { before { it.result = false } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/sidebar/video/UnlockEnhanceContours.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.video import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object UnlockEnhanceContours : BaseHook() { override fun init() { dexKitBridge.findMethod { matcher { usingStrings = listOf("ro.vendor.media.video.frc.support") } }.forEach { val qaq = it.getClassInstance(EzXHelper.classLoader) var counter = 0 dexKitBridge.findMethod { matcher { declaredClass = qaq.name returnType = "boolean" paramTypes = listOf("java.lang.String") } }.forEach { methods -> counter++ if (counter == 3) { methods.getMethodInstance(EzXHelper.classLoader).createHook { returnConstant(true) } } } val tat = dexKitBridge.findMethod { matcher { usingStrings = listOf("debug.config.media.video.ais.support") declaredClass = qaq.name } }.first().getMethodInstance(EzXHelper.classLoader) val newChar = tat.name.toCharArray() for (i in newChar.indices) { newChar[i]++ } val newName = String(newChar) tat.declaringClass.methodFinder() .filterByName(newName) .first().createHook { returnConstant(true) } } /*initDexKit(lpparam) try { val result = Objects.requireNonNull( SecurityCenterDexKit.mSecurityCenterResultClassMap["FrcSupport"] ) for (descriptor in result) { val frcSupport = descriptor.getClassInstance(lpparam.classLoader) XposedLogUtils.logI("frcSupport class is $frcSupport") var counter = 0 dexKitBridge.findMethod { methodDeclareClass = frcSupport.name methodReturnType = "boolean" methodParamTypes = arrayOf("java.lang.String") }.forEach { methods -> counter++ if (counter == 3) { methods.getMethodInstance(EzXHelper.classLoader).createHook { returnConstant(true) } } } } } catch (e: Throwable) { logE("FrcSupport", e) } try { val result = Objects.requireNonNull( SecurityCenterDexKit.mSecurityCenterResultMap["AisSupport"] ) for (descriptor in result) { val aisSupport = descriptor.getMethodInstance(lpparam.classLoader) XposedLogUtils.logI("aisSupport method is $aisSupport") val newChar = aisSupport.name.toCharArray() for (i in newChar.indices) { newChar[i]++ } val newName = String(newChar) aisSupport.declaringClass.methodFinder() .filterByName(newName) .first().createHook { returnConstant(true) } } } catch (e: Throwable) { logE("AisSupport", e) } closeDexKit()*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/sidebar/video/UnlockMemc.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.video import com.github.kyuubiran.ezxhelper.EzXHelper.classLoader import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object UnlockMemc : BaseHook() { override fun init() { dexKitBridge.findClass { matcher { usingStrings = listOf("ro.vendor.media.video.frc.support") } }.map { val frcSupport = it.getInstance(classLoader) var counter = 0 dexKitBridge.findMethod { matcher { declaredClass = frcSupport.name returnType = "boolean" paramTypes = listOf("java.lang.String") } }.forEach { methods -> counter++ if (counter == 5) { methods.getMethodInstance(classLoader).createHook { returnConstant(true) } } } } /* initDexKit(lpparam) try { val result = Objects.requireNonNull( SecurityCenterDexKit.mSecurityCenterResultClassMap["FrcSupport"] ) for (descriptor in result) { val frcSupport = descriptor.getClassInstance(lpparam.classLoader) XposedLogUtils.logI("frcSupport class is $frcSupport") var counter = 0 dexKitBridge.findMethod { methodDeclareClass = frcSupport.name methodReturnType = "boolean" methodParamTypes = arrayOf("java.lang.String") }.forEach { methods -> counter++ if (counter == 5) { methods.getMethodInstance(classLoader).createHook { returnConstant(true) } } } } } catch (e: Throwable) { logE("FrcSupport", e) } closeDexKit()*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/securitycenter/sidebar/video/UnlockSuperResolution.kt ================================================ package com.sevtinge.cemiuiler.module.hook.securitycenter.sidebar.video import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object UnlockSuperResolution : BaseHook() { override fun init() { dexKitBridge.findClass { matcher { usingStrings = listOf("ro.vendor.media.video.frc.support") } }.map { val qaq = it.getInstance(EzXHelper.classLoader) var counter = 0 dexKitBridge.findMethod { matcher { declaredClass = qaq.name returnType = "boolean" paramTypes = listOf("java.lang.String") } }.forEach { methods -> counter++ if (counter == 1) { methods.getMethodInstance(EzXHelper.classLoader).createHook { returnConstant(true) } } } dexKitBridge.findMethod { matcher { declaredClass = qaq.name usingStrings = listOf("debug.config.media.video.ais.support") } }.first().getMethodInstance(EzXHelper.classLoader).createHook { returnConstant(true) } } /* initDexKit(lpparam) try { val result = Objects.requireNonNull( SecurityCenterDexKit.mSecurityCenterResultClassMap["FrcSupport"] ) for (descriptor in result) { val frcSupport = descriptor.getClassInstance(lpparam.classLoader) XposedLogUtils.logI("frcSupport class is $frcSupport") var counter = 0 dexKitBridge.findMethod { methodDeclareClass = frcSupport.name methodReturnType = "boolean" methodParamTypes = arrayOf("java.lang.String") }.forEach { methods -> counter++ if (counter == 1) { methods.getMethodInstance(EzXHelper.classLoader).createHook { returnConstant(true) } } } } } catch (e: Throwable) { logE("FrcSupport", e) } try { val result = Objects.requireNonNull( SecurityCenterDexKit.mSecurityCenterResultMap["AisSupport"] ) for (descriptor in result) { val aisSupport = descriptor.getMethodInstance(lpparam.classLoader) XposedLogUtils.logI("aisSupport method is $aisSupport") if (aisSupport.returnType == Boolean::class.javaPrimitiveType) { XposedBridge.hookMethod(aisSupport, XC_MethodReplacement.returnConstant(true)) } } } catch (e: Throwable) { logE("AisSupport", e) } closeDexKit()*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/settings/CemiuilerSettings.java ================================================ package com.sevtinge.cemiuiler.module.hook.settings; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; import android.os.UserHandle; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.ui.MainActivity; import com.sevtinge.cemiuiler.utils.Helpers; import java.util.ArrayList; import java.util.List; import de.robv.android.xposed.XposedHelpers; import moralnorm.os.Build; public class CemiuilerSettings extends BaseHook { private int settingsIconResId; private Class mPreferenceHeader; int mIconModeInt = mPrefsMap.getStringAsInt("prefs_key_settings_icon_mode", 0); @Override public void init() { addIconResource(); Class mMiuiSettings = findClassIfExists("com.android.settings.MiuiSettings"); findAndHookMethod(mMiuiSettings, "updateHeaderList", List.class, new MethodHook() { @Override @SuppressLint("DiscouragedApi") protected void after(MethodHookParam param) throws Throwable { if (param.args[0] == null) return; Context mContext = ((Activity) param.thisObject).getBaseContext(); int opt = Integer.parseInt(mPrefsMap.getString("settings_icon", "0")); if (opt == 0) return; Resources modRes = Helpers.getModuleRes(mContext); mPreferenceHeader = findClassIfExists("com.android.settingslib.miuisettings.preference.PreferenceActivity$Header"); if (mPreferenceHeader == null) return; Intent mIntent = new Intent(); mIntent.putExtra("isDisplayHomeAsUpEnabled", true); mIntent.setClassName(Helpers.mAppModulePkg, MainActivity.class.getCanonicalName()); Object header = XposedHelpers.newInstance(mPreferenceHeader); XposedHelpers.setLongField(header, "id", 666); XposedHelpers.setObjectField(header, "intent", mIntent); XposedHelpers.setIntField(header, "iconRes", settingsIconResId); XposedHelpers.setObjectField(header, "title", modRes.getString(R.string.app_name)); Bundle bundle = new Bundle(); ArrayList users = new ArrayList<>(); users.add((UserHandle) XposedHelpers.newInstance(UserHandle.class, 0)); bundle.putParcelableArrayList("header_user", users); XposedHelpers.setObjectField(header, "extras", bundle); int themes = mContext.getResources().getIdentifier("launcher_settings", "id", mContext.getPackageName()); int special = mContext.getResources().getIdentifier("other_special_feature_settings", "id", mContext.getPackageName()); int timer = mContext.getResources().getIdentifier("app_timer", "id", mContext.getPackageName()); List headers = (List) param.args[0]; int position = 0; for (Object head : headers) { position++; long id = XposedHelpers.getLongField(head, "id"); if (opt == 1 && id == -1) { headers.add(position - 1, header); } else if (opt == 2 && id == themes) { headers.add(position, header); } else if (opt == 3 && id == (Integer.parseInt(Build.getMiuiVersionCode()) < 14 ? special : timer)) { headers.add(position, header); } } if (headers.size() > 25) { headers.add(25, header); } else { headers.add(header); } } }); } private void addIconResource() { if (mIconModeInt == 0) { settingsIconResId = mResHook.addResource("ic_cemiuiler_settings", R.drawable.ic_cemiuiler_settings_v140); } else { settingsIconResId = mResHook.addResource("ic_cemiuiler_settings", R.drawable.ic_cemiuiler_settings_v130); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/settings/NotificationImportance.java ================================================ package com.sevtinge.cemiuiler.module.hook.settings; import android.app.NotificationChannel; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import de.robv.android.xposed.XposedHelpers; public class NotificationImportance extends BaseHook { Class mBaseNotificationSettings; Class mChannelNotificationSettings; @Override public void init() { mBaseNotificationSettings = findClassIfExists("com.android.settings.notification.BaseNotificationSettings"); mChannelNotificationSettings = findClassIfExists("com.android.settings.notification.ChannelNotificationSettings"); hookAllMethods(mBaseNotificationSettings, "setPrefVisible", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Object pref = param.args[0]; if (pref != null) { String prefKey = (String) XposedHelpers.callMethod(pref, "getKey"); if ("importance".equals(prefKey)) { param.args[1] = true; } } } }); findAndHookMethod(mChannelNotificationSettings, "setupChannelDefaultPrefs", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Object pref = XposedHelpers.callMethod(param.thisObject, "findPreference", "importance"); XposedHelpers.setObjectField(param.thisObject, "mImportance", pref); int mBackupImportance = (int) XposedHelpers.getObjectField(param.thisObject, "mBackupImportance"); if (mBackupImportance > 0) { int index = (int) XposedHelpers.callMethod(pref, "findSpinnerIndexOfValue", String.valueOf(mBackupImportance)); if (index > -1) { XposedHelpers.callMethod(pref, "setValueIndex", index); } Class ImportanceListener = XposedHelpers.findClassIfExists("androidx.preference.Preference$OnPreferenceChangeListener", lpparam.classLoader); InvocationHandler handler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("onPreferenceChange")) { int mBackupImportance = Integer.parseInt((String) args[1]); XposedHelpers.setObjectField(param.thisObject, "mBackupImportance", mBackupImportance); NotificationChannel mChannel = (NotificationChannel) XposedHelpers.getObjectField(param.thisObject, "mChannel"); mChannel.setImportance(mBackupImportance); XposedHelpers.callMethod(mChannel, "lockFields", 4); Object mBackend = XposedHelpers.getObjectField(param.thisObject, "mBackend"); String mPkg = (String) XposedHelpers.getObjectField(param.thisObject, "mPkg"); int mUid = (int) XposedHelpers.getObjectField(param.thisObject, "mUid"); XposedHelpers.callMethod(mBackend, "updateChannel", mPkg, mUid, mChannel); XposedHelpers.callMethod(param.thisObject, "updateDependents", false); } return true; } }; Object mImportanceListener = Proxy.newProxyInstance( lpparam.classLoader, new Class[]{ImportanceListener}, handler ); XposedHelpers.callMethod(pref, "setOnPreferenceChangeListener", mImportanceListener); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/settings/VolumeSeparateControlForSettings.java ================================================ package com.sevtinge.cemiuiler.module.hook.settings; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.os.Bundle; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import de.robv.android.xposed.XposedHelpers; public class VolumeSeparateControlForSettings extends BaseHook { Class mVsbCls; Class mPreferenceGroupCls; Class mPreferenceCls; public static int mSystemResId; public static int mCallsResId; public static int mNotificationVolumeResId; @Override public void init() { mVsbCls = findClassIfExists("com.android.settings.sound.VolumeSeekBarPreference"); mPreferenceGroupCls = findClassIfExists("androidx.preference.PreferenceGroup"); mPreferenceCls = findClassIfExists("androidx.preference.Preference"); findAndHookMethod("com.android.settings.MiuiSoundSettings", "onCreate", Bundle.class, new MethodHook() { @SuppressLint("DiscouragedApi") @Override protected void after(MethodHookParam param) throws Throwable { Object fragment = param.thisObject; Context context = (Context) XposedHelpers.callMethod(fragment, "getActivity"); Resources modRes = Helpers.getModuleRes(context); int order = 6; Method[] initSeekBar; String addPreference = "addPreference"; try { initSeekBar = XposedHelpers.findMethodsByExactParameters(fragment.getClass(), void.class, String.class, int.class, int.class); if (mVsbCls == null || initSeekBar.length == 0) { XposedLogUtils.logI(TAG, "Unable to find class/method in Settings to hook"); return; } else { initSeekBar[0].setAccessible(true); } Method[] methods = XposedHelpers.findMethodsByExactParameters(mPreferenceGroupCls, void.class, mPreferenceCls); for (Method method : methods) { if (Modifier.isPublic(method.getModifiers())) { addPreference = method.getName(); break; } } } catch (Throwable t) { XposedLogUtils.logI(TAG, "Unable to find class/method in Settings to hook"); return; } Object media = XposedHelpers.callMethod(fragment, "findPreference", "media_volume"); if (media != null) order = (int) XposedHelpers.callMethod(media, "getOrder"); Object prefScreen = XposedHelpers.callMethod(fragment, "getPreferenceScreen"); Object pref = XposedHelpers.newInstance(mVsbCls, context); XposedHelpers.callMethod(pref, "setKey", "system_volume"); XposedHelpers.callMethod(pref, "setTitle", modRes.getString(R.string.system_volume)); XposedHelpers.callMethod(pref, "setPersistent", true); XposedHelpers.callMethod(prefScreen, addPreference, pref); initSeekBar[0].invoke(fragment, "system_volume", 1, context.getResources().getIdentifier("ic_audio_vol", "drawable", context.getPackageName())); XposedHelpers.callMethod(pref, "setOrder", order); pref = XposedHelpers.newInstance(mVsbCls, context); XposedHelpers.callMethod(pref, "setKey", "notification_volume"); XposedHelpers.callMethod(pref, "setTitle", modRes.getString(R.string.notification_volume)); XposedHelpers.callMethod(pref, "setPersistent", true); XposedHelpers.callMethod(prefScreen, addPreference, pref); initSeekBar[0].invoke(fragment, "notification_volume", 5, context.getResources().getIdentifier("ic_audio_ring_notif", "drawable", context.getPackageName())); XposedHelpers.callMethod(pref, "setOrder", order); Object mRingVolume = XposedHelpers.callMethod(param.thisObject, "findPreference", "ring_volume"); XposedHelpers.callMethod(mRingVolume, "setTitle", mCallsResId); } }); } public static void initRes() { mSystemResId = XposedInit.mResHook.addResource("ic_audio_system", R.drawable.ic_audio_system); mNotificationVolumeResId = XposedInit.mResHook.addResource("ic_notification_volume", R.drawable.ic_miui_volume_notification); /*mCallsResId = XposedInit.mResHook.addResource("ring_volume_option_newtitle", R.string.calls);*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/AllRotations.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class AllRotations extends BaseHook { @Override public void init() { hookAllConstructors("com.android.server.wm.DisplayRotation", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.setIntField(param.thisObject, "mAllowAllRotations", mPrefsMap.getBoolean("system_framework_screen_all_rotations") ? 1 : 0); } }); } /*public static void initZygote() { XposedInit.mResourcesHook.setObjectReplacement("android", "bool", "config_allowAllRotations", mPrefsMap.getBoolean("system_framework_screen_all_rotations")); }*/ } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/AllowUninstall.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import dalvik.system.PathClassLoader; import de.robv.android.xposed.IXposedHookZygoteInit; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; public class AllowUninstall implements IXposedHookZygoteInit { private final String SecurityManagerServiceName = "com.miui.server.SecurityManagerService$1"; private PathClassLoader servicesClassLoader = null; private Class SecurityManagerServiceClazz = null; private java.util.Set pathClassLoaderHook = null; @Override public void initZygote(StartupParam startupParam) { XposedBridge.log("[Cemiuiler][I][AllowUninstall]: hook all PathClassLoader Constructors"); pathClassLoaderHook = XposedBridge.hookAllConstructors(PathClassLoader.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) { String path = param.args[0].toString(); if (path.contains("/system/framework/services.jar")) { XposedBridge.log("[Cemiuiler][I][AllowUninstall]: find services.jar ClassLoader"); try { servicesClassLoader = (PathClassLoader) param.thisObject; SecurityManagerServiceClazz = XposedHelpers.findClass( SecurityManagerServiceName, servicesClassLoader); XposedBridge.log("[Cemiuiler][I][AllowUninstall]: findClass SecurityManagerService$1"); XposedHelpers.findAndHookMethod(SecurityManagerServiceClazz, "run", new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(MethodHookParam unused) { XposedBridge.log("[Cemiuiler][I][AllowUninstall]: hooked checkSystemSelfProtection invoke"); return null; } }); XposedBridge.log("[Cemiuiler][I][AllowUninstall]: hook method 'SecurityManagerService$1.run()'"); } catch (Exception e) { XposedBridge.log("[Cemiuiler][E][AllowUninstall]: AllowUninstall Exception!"); e.printStackTrace(); } finally { for (Unhook hook : pathClassLoaderHook) { hook.unhook(); } XposedBridge.log("[Cemiuiler][I][AllowUninstall]: unhook all PathClassLoader Constructors"); } } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/AllowUntrustedTouch.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class AllowUntrustedTouch extends BaseHook { Class mInputManager; @Override public void init() { mInputManager = findClassIfExists("android.hardware.input.InputManager"); hookAllMethods(mInputManager, "getBlockUntrustedTouchesMode", XC_MethodReplacement.returnConstant(0));// error } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/AppDisableService.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.ArrayList; import java.util.Arrays; public class AppDisableService extends BaseHook { public ArrayList mMiuiCoreApps = new ArrayList<>(Arrays.asList( "com.lbe.security.miui", "com.miui.securitycenter" )); @Override public void init() { findAndHookMethod("com.android.server.pm.PackageManagerServiceImpl", "canBeDisabled", String.class, int.class, new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { boolean canBeDisabled = (boolean) param.getResult(); if (!canBeDisabled && !mMiuiCoreApps.contains(param.args[0])) { param.setResult(true); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/AppLinkVerify.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; public class AppLinkVerify extends BaseHook { @Override public void init() { try { hookAllMethods("com.android.server.pm.verify.domain.DomainVerificationUtils", "isDomainVerificationIntent", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(false); } } ); } catch (Throwable t) { XposedLogUtils.logE(TAG, t); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/BackgroundBlurDrawable.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework import android.graphics.Canvas import com.sevtinge.cemiuiler.utils.HookUtils import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import com.sevtinge.cemiuiler.utils.log.XposedLogUtils.logI import de.robv.android.xposed.IXposedHookZygoteInit import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge class BackgroundBlurDrawable : IXposedHookZygoteInit { override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) { val classLoader = startupParam.javaClass.classLoader val mBackgroundBlurDrawableClass = classLoader?.let { HookUtils.getClass("com.android.internal.graphics.drawable.BackgroundBlurDrawable", it) } ?: return // 为 BackgroundBlurDrawable 应当增加一个判断 // 此处应该可以为AOSP提交修复补丁 XposedBridge.hookAllMethods( mBackgroundBlurDrawableClass, "draw", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { val canvas = param.args[0] as Canvas if (!canvas.isHardwareAccelerated) { XposedLogUtils.logI("BackgroundBlurDrawable canvas is not HardwareAccelerated.") param.result = null } } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/CleanOpenMenu.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.BadParcelableException; import android.os.Handler; import android.util.Pair; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.PrefsUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.util.Iterator; import java.util.List; import java.util.Set; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; public class CleanOpenMenu extends BaseHook { Class mPackageManagerService; @Override public void init() { mPackageManagerService = findClassIfExists("com.android.server.pm.PackageManagerService"); findAndHookMethod(mPackageManagerService, "systemReady", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); Handler mHandler = (Handler) XposedHelpers.getObjectField(param.thisObject, "mHandler"); new PrefsUtils.SharedPrefsObserver(mContext, mHandler) { @Override public void onChange(Uri uri) { try { String type = uri.getPathSegments().get(1); String key = uri.getPathSegments().get(2); if (!key.contains("pref_key_system_framework_clean_open_apps")) return; switch (type) { case "stringset" -> mPrefsMap.put(key, Helpers.getSharedStringSetPref(mContext, key)); case "integer" -> mPrefsMap.put(key, Helpers.getSharedIntPref(mContext, key, 0)); } } catch (Throwable t) { XposedLogUtils.logE(TAG, t); } } }; } }); MethodHook hook = new MethodHook() { @Override @SuppressWarnings("unchecked") protected void after(MethodHookParam param) { try { if (param.args[0] == null) return; if (param.args.length < 6) return; Intent origIntent = (Intent) param.args[0]; Intent intent = (Intent) origIntent.clone(); String action = intent.getAction(); // XposedBridge.log(action + ": " + intent.getType() + " | " + intent.getDataString()); if (!Intent.ACTION_VIEW.equals(action)) return; if (intent.hasExtra("Cemiuiler") && intent.getBooleanExtra("Cemiuiler", false)) return; String scheme = intent.getScheme(); boolean validSchemes = "http".equals(scheme) || "https".equals(scheme) || "vnd.youtube".equals(scheme); if (intent.getType() == null && !validSchemes) return; Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); String mimeType = getContentType(mContext, intent); // XposedBridge.log("mimeType: " + mimeType); String key = "system_framework_clean_open_apps"; Set selectedApps = mPrefsMap.getStringSet(key); List resolved = (List) param.getResult(); ResolveInfo resolveInfo; PackageManager pm = mContext.getPackageManager(); Iterator itr = resolved.iterator(); while (itr.hasNext()) { resolveInfo = itr.next(); Pair isRemove = isRemoveApp(false, mContext, resolveInfo.activityInfo.packageName, selectedApps, mimeType); boolean hasDual = false; try { hasDual = XposedHelpers.callMethod(pm, "getPackageInfoAsUser", resolveInfo.activityInfo.packageName, 0, 999) != null; } catch (Throwable ignore) { } if ((isRemove.first && !hasDual) || isRemove.first && hasDual && isRemove.second) itr.remove(); } param.setResult(resolved); } catch (Throwable t) { if (!(t instanceof BadParcelableException)) XposedBridge.log(t); } } }; String ActQueryService = isMoreAndroidVersion(33) ? "com.android.server.pm.ComputerEngine" : "com.android.server.pm.PackageManagerService$ComputerEngine"; Helpers.hookAllMethods(ActQueryService, lpparam.classLoader, "queryIntentActivitiesInternal", hook); // if (!findAndHookMethodSilently(mPackageManagerService, "queryIntentActivitiesInternal", Intent.class, String.class, int.class, int.class, int.class, boolean.class, boolean.class, hook)) // findAndHookMethod(mPackageManagerService, "queryIntentActivitiesInternal", Intent.class, String.class, int.class, int.class, hook);//error } // if (!findAndHookMethodSilently(mPackageManagerService, "queryIntentActivitiesInternal", Intent.class, String.class, long.class, long.class, int.class, boolean.class, boolean.class, hook)) // findAndHookMethod(mPackageManagerService, "queryIntentActivitiesInternal", Intent.class, String.class, long.class, int.class, hook); //} // 存在问题 private static Pair isRemoveApp(boolean dynamic, Context context, String pkgName, Set selectedApps, String mimeType) { String key = "system_framework_clean_open_apps"; int mimeFlags0; int mimeFlags999; if (dynamic) { mimeFlags0 = Helpers.getSharedIntPref(context, "pref_key_" + key + "_" + pkgName + "|0", Helpers.MimeType.ALL); mimeFlags999 = Helpers.getSharedIntPref(context, "pref_key_" + key + "_" + pkgName + "|999", Helpers.MimeType.ALL); } else { mimeFlags0 = mPrefsMap.getInt(key + "_" + pkgName + "|0", Helpers.MimeType.ALL); mimeFlags999 = mPrefsMap.getInt(key + "_" + pkgName + "|999", Helpers.MimeType.ALL); } boolean removeOriginal = (selectedApps.contains(pkgName) || selectedApps.contains(pkgName + "|0")) && hideMimeType(mimeFlags0, mimeType); boolean removeDual = selectedApps.contains(pkgName + "|999") && hideMimeType(mimeFlags999, mimeType); return new Pair(removeOriginal, removeDual); } private static String getContentType(Context context, Intent intent) { String scheme = intent.getScheme(); boolean linkSchemes = "http".equals(scheme) || "https".equals(scheme) || "vnd.youtube".equals(scheme); String mimeType = intent.getType(); if (mimeType == null && linkSchemes) mimeType = "link/*"; if (mimeType == null && intent.getData() != null) try { mimeType = context.getContentResolver().getType(intent.getData()); } catch (Throwable ignore) { } return mimeType; } private static boolean hideMimeType(int mimeFlags, String mimeType) { int dataType = Helpers.MimeType.OTHERS; if (mimeType != null) if (mimeType.startsWith("image/")) dataType = Helpers.MimeType.IMAGE; else if (mimeType.startsWith("audio/")) dataType = Helpers.MimeType.AUDIO; else if (mimeType.startsWith("video/")) dataType = Helpers.MimeType.VIDEO; else if (mimeType.startsWith("text/") || mimeType.startsWith("application/pdf") || mimeType.startsWith("application/msword") || mimeType.startsWith("application/vnd.ms-") || mimeType.startsWith("application/vnd.openxmlformats-")) dataType = Helpers.MimeType.DOCUMENT; else if (mimeType.startsWith("application/vnd.android.package-archive") || mimeType.startsWith("application/zip") || mimeType.startsWith("application/x-zip") || mimeType.startsWith("application/octet-stream") || mimeType.startsWith("application/rar") || mimeType.startsWith("application/x-rar") || mimeType.startsWith("application/x-tar") || mimeType.startsWith("application/x-bzip") || mimeType.startsWith("application/gzip") || mimeType.startsWith("application/x-lz") || mimeType.startsWith("application/x-compress") || mimeType.startsWith("application/x-7z") || mimeType.startsWith("application/java-archive")) dataType = Helpers.MimeType.ARCHIVE; else if (mimeType.startsWith("link/")) dataType = Helpers.MimeType.LINK; return (mimeFlags & dataType) == dataType; } public static void initRes() { Helpers.hookAllMethods("miui.securityspace.XSpaceResolverActivityHelper.ResolverActivityRunner", null, "run", new Helpers.MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Intent mOriginalIntent = (Intent) XposedHelpers.getObjectField(param.thisObject, "mOriginalIntent"); if (mOriginalIntent == null) return; String action = mOriginalIntent.getAction(); if (!Intent.ACTION_VIEW.equals(action)) return; // if (mOriginalIntent.getDataString() != null && mOriginalIntent.getDataString().contains(":")) return; Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); String mAimPackageName = (String) XposedHelpers.getObjectField(param.thisObject, "mAimPackageName"); if (mContext == null || mAimPackageName == null) return; Set selectedApps = Helpers.getSharedStringSetPref(mContext, "system_framework_clean_open_apps"); String mimeType = getContentType(mContext, mOriginalIntent); Pair isRemove = isRemoveApp(true, mContext, mAimPackageName, selectedApps, mimeType); View mRootView = (View) XposedHelpers.getObjectField(param.thisObject, "mRootView"); int appResId1 = mContext.getResources().getIdentifier("app1", "id", "android.miui"); int appResId2 = mContext.getResources().getIdentifier("app2", "id", "android.miui"); View originalApp = mRootView.findViewById(appResId1); View dualApp = mRootView.findViewById(appResId2); if (isRemove.first) dualApp.performClick(); else if (isRemove.second) originalApp.performClick(); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/CleanShareMenu.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.BadParcelableException; import android.os.Handler; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.PrefsUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.util.Iterator; import java.util.List; import java.util.Set; import de.robv.android.xposed.XposedHelpers; public class CleanShareMenu extends BaseHook { Class mPackageManagerService; @Override public void init() { mPackageManagerService = findClassIfExists("com.android.server.pm.PackageManagerService"); findAndHookMethod(mPackageManagerService, "systemReady", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); Handler mHandler = (Handler) XposedHelpers.getObjectField(param.thisObject, "mHandler"); new PrefsUtils.SharedPrefsObserver(mContext, mHandler, "prefs_key_system_framework_clean_share_apps") { @Override public void onChange(String name) { mPrefsMap.put(name, PrefsUtils.getSharedStringSetPrefs(mContext, name)); } }; } }); MethodHook hook = new MethodHook() { @Override @SuppressWarnings("unchecked") protected void after(MethodHookParam param) throws Throwable { try { if (param.args[0] == null) return; Intent origIntent = (Intent) param.args[0]; String action = origIntent.getAction(); if (action == null) return; if (!action.equals(Intent.ACTION_SEND) && !action.equals(Intent.ACTION_SENDTO) && !action.equals(Intent.ACTION_SEND_MULTIPLE)) return; Intent intent = (Intent) origIntent.clone(); if (intent.getDataString() != null && intent.getDataString().contains(":")) return; if (intent.hasExtra("Cemiuiler") && intent.getBooleanExtra("Cemiuiler", false)) return; Set selectedApps = mPrefsMap.getStringSet("system_framework_clean_share_apps"); List resolved = (List) param.getResult(); ResolveInfo resolveInfo; Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); PackageManager pm = mContext.getPackageManager(); Iterator itr = resolved.iterator(); while (itr.hasNext()) { resolveInfo = itr.next(); boolean removeOriginal = selectedApps.contains(resolveInfo.activityInfo.packageName) || selectedApps.contains(resolveInfo.activityInfo.packageName + "|0"); boolean removeDual = selectedApps.contains(resolveInfo.activityInfo.packageName + "|999"); boolean hasDual = false; try { hasDual = XposedHelpers.callMethod(pm, "getPackageInfoAsUser", resolveInfo.activityInfo.packageName, 0, 999) != null; } catch (Throwable ignore) { } if ((removeOriginal && !hasDual) || removeOriginal && hasDual && removeDual) itr.remove(); } param.setResult(resolved); } catch (Throwable t) { if (!(t instanceof BadParcelableException)) XposedLogUtils.logE(TAG, t); } } }; String ActQueryService = isMoreAndroidVersion(33) ? "com.android.server.pm.ComputerEngine" : "com.android.server.pm.PackageManagerService$ComputerEngine"; Helpers.hookAllMethods(ActQueryService, lpparam.classLoader, "queryIntentActivitiesInternal", hook); // if (!findAndHookMethodSilently(mPackageManagerService, "queryIntentActivitiesInternal", Intent.class, String.class, int.class, int.class, int.class, boolean.class, boolean.class, hook)) // findAndHookMethod(mPackageManagerService, "queryIntentActivitiesInternal", Intent.class, String.class, int.class, int.class, hook);//error } // if (!findAndHookMethodSilently(mPackageManagerService, "queryIntentActivitiesInternal", Intent.class, String.class, long.class, long.class, int.class, boolean.class, boolean.class, hook)) // findAndHookMethod(mPackageManagerService, "queryIntentActivitiesInternal", Intent.class, String.class, long.class, int.class, hook); //} public static void initRes() { Helpers.hookAllMethods("miui.securityspace.XSpaceResolverActivityHelper.ResolverActivityRunner", null, "run", new Helpers.MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Intent mOriginalIntent = (Intent) XposedHelpers.getObjectField(param.thisObject, "mOriginalIntent"); if (mOriginalIntent == null) return; String action = mOriginalIntent.getAction(); if (action == null) return; if (!action.equals(Intent.ACTION_SEND) && !action.equals(Intent.ACTION_SENDTO) && !action.equals(Intent.ACTION_SEND_MULTIPLE)) return; if (mOriginalIntent.getDataString() != null && mOriginalIntent.getDataString().contains(":")) return; Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); String mAimPackageName = (String) XposedHelpers.getObjectField(param.thisObject, "mAimPackageName"); if (mContext == null || mAimPackageName == null) return; Set selectedApps = PrefsUtils.getSharedStringSetPrefs(mContext, "prefs_key_system_framework_clean_share_apps"); View mRootView = (View) XposedHelpers.getObjectField(param.thisObject, "mRootView"); int appResId1 = mContext.getResources().getIdentifier("app1", "id", "android.miui"); int appResId2 = mContext.getResources().getIdentifier("app2", "id", "android.miui"); boolean removeOriginal = selectedApps.contains(mAimPackageName) || selectedApps.contains(mAimPackageName + "|0"); boolean removeDual = selectedApps.contains(mAimPackageName + "|999"); View originalApp = mRootView.findViewById(appResId1); View dualApp = mRootView.findViewById(appResId2); if (removeOriginal) dualApp.performClick(); else if (removeDual) originalApp.performClick(); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/DeleteOnPostNotification.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework import com.sevtinge.cemiuiler.module.base.BaseHook object DeleteOnPostNotification : BaseHook() { override fun init() { findAndHookMethod("com.android.server.wm.AlertWindowNotification", "onPostNotification", object : MethodHook() { override fun before(param: MethodHookParam?) { param?.result = null } } ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/DisableCleaner.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework import com.sevtinge.cemiuiler.module.base.BaseHook object DisableCleaner : BaseHook() { override fun init() { hookAllMethods("com.android.server.am.ActivityManagerService", "checkExcessivePowerUsage", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = null } } ) hookAllMethods("com.android.server.am.ActivityManagerShellCommand", "runKillAll", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = null } } ) hookAllMethods("com.android.server.am.CameraBooster", "boostCameraIfNeeded", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = null } } ) hookAllMethods("com.android.server.am.OomAdjuster", "shouldKillExcessiveProcesses", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = false } } ) hookAllMethods("com.android.server.am.OomAdjuster", "updateAndTrimProcessLSP", object : MethodHook() { override fun before(param: MethodHookParam) { param.args[2] = 0 } } ) hookAllMethods("com.android.server.am.PhantomProcessList", "trimPhantomProcessesIfNecessary", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = null } } ) hookAllMethods("com.android.server.am.ProcessMemoryCleaner", "checkBackgroundProcCompact", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = null } } ) hookAllMethods("com.android.server.am.ProcessPowerCleaner", "handleAutoLockOff", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = null } } ) hookAllMethods("com.android.server.am.SystemPressureController", "nStartPressureMonitor", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = null } } ) hookAllMethods("com.android.server.wm.RecentTasks", "trimInactiveRecentTasks", object : MethodHook() { override fun before(param: MethodHookParam) { param.result = null } } ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/DisableFreeformBlackList.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.ArrayList; import java.util.List; import de.robv.android.xposed.XC_MethodReplacement; public class DisableFreeformBlackList extends BaseHook { Class mTaskCls; Class mMiuiMultiWindowAdapter; Class mMiuiMultiWindowUtils; @Override public void init() { mTaskCls = findClassIfExists("com.android.server.wm.Task"); mMiuiMultiWindowAdapter = findClassIfExists("android.util.MiuiMultiWindowAdapter"); mMiuiMultiWindowUtils = findClassIfExists("android.util.MiuiMultiWindowUtils"); MethodHook clearHook = new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { List blackList = (List) param.getResult(); if (blackList != null) blackList.clear(); param.setResult(blackList); } }; hookAllMethods(mMiuiMultiWindowAdapter, "getFreeformBlackList", clearHook); hookAllMethods(mMiuiMultiWindowAdapter, "getFreeformBlackListFromCloud", clearHook); hookAllMethods(mMiuiMultiWindowAdapter, "setFreeformBlackList", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { List blackList = new ArrayList(); blackList.add("ab.cd.xyz"); param.args[0] = blackList; } }); findAndHookMethod(mMiuiMultiWindowUtils, "isForceResizeable", XC_MethodReplacement.returnConstant(true)); findAndHookMethod(mMiuiMultiWindowUtils, "supportFreeform", XC_MethodReplacement.returnConstant(true)); // 强制所有活动设为可以调整大小 /*findAndHookMethod(mTaskCls, "isResizeable", XC_MethodReplacement.returnConstant(true));*/ mResHook.setResReplacement("android", "array", "freeform_black_list", R.array.miui_freeform_black_list); mResHook.setResReplacement("com.miui.rom", "array", "freeform_black_list", R.array.miui_freeform_black_list); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/DisablePinVerifyPer72h.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class DisablePinVerifyPer72h extends BaseHook { @Override public void init() { findAndHookMethod("com.android.server.locksettings.LockSettingsStrongAuth", "rescheduleStrongAuthTimeoutAlarm", long.class, int.class, XC_MethodReplacement.DO_NOTHING); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/FlagSecure.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import android.os.Build; import android.util.Log; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.function.BiConsumer; import java.util.function.BiPredicate; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; public class FlagSecure extends BaseHook { /*@Override public void init() { findAndHookMethod("com.android.server.wm.WindowState", "isSecureLocked", XC_MethodReplacement.returnConstant(false)); }*/ private final static Method deoptimizeMethod; static { Method m = null; try { m = XposedBridge.class.getDeclaredMethod("deoptimizeMethod", Member.class); } catch (Throwable t) { XposedBridge.log(t); } deoptimizeMethod = m; } static void deoptimizeMethod(Class c, String n) throws InvocationTargetException, IllegalAccessException { for (Method m : c.getDeclaredMethods()) { if (deoptimizeMethod != null && m.getName().equals(n)) { deoptimizeMethod.invoke(null, m); Log.d("DisableFlagSecure", "Deoptimized " + m); } } } @Override public void init() { if (lpparam.packageName.equals("android")) { try { Class windowsState = XposedHelpers.findClass("com.android.server.wm.WindowState", lpparam.classLoader); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { XposedHelpers.findAndHookMethod( windowsState, "isSecureLocked", XC_MethodReplacement.returnConstant(false)); } else { XposedHelpers.findAndHookMethod( "com.android.server.wm.WindowManagerService", lpparam.classLoader, "isSecureLocked", windowsState, XC_MethodReplacement.returnConstant(false)); } } catch (Throwable t) { XposedBridge.log(t); } try { deoptimizeMethod(XposedHelpers.findClass("com.android.server.wm.WindowStateAnimator", lpparam.classLoader), "createSurfaceLocked"); var c = XposedHelpers.findClass("com.android.server.display.DisplayManagerService", lpparam.classLoader); deoptimizeMethod(c, "setUserPreferredModeForDisplayLocked"); deoptimizeMethod(c, "setUserPreferredDisplayModeInternal"); c = XposedHelpers.findClass("com.android.server.wm.InsetsPolicy$InsetsPolicyAnimationControlListener", lpparam.classLoader); for (var m : c.getDeclaredConstructors()) { deoptimizeMethod.invoke(null, m); } c = XposedHelpers.findClass("com.android.server.wm.InsetsPolicy", lpparam.classLoader); deoptimizeMethod(c, "startAnimation"); deoptimizeMethod(c, "controlAnimationUnchecked"); for (int i = 0; i < 20; i++) { c = XposedHelpers.findClassIfExists("com.android.server.wm.DisplayContent$$ExternalSyntheticLambda" + i, lpparam.classLoader); if (c != null && BiPredicate.class.isAssignableFrom(c)) { deoptimizeMethod(c, "test"); } } c = XposedHelpers.findClass("com.android.server.wm.WindowManagerService", lpparam.classLoader); deoptimizeMethod(c, "relayoutWindow"); for (int i = 0; i < 20; i++) { c = XposedHelpers.findClassIfExists("com.android.server.wm.RootWindowContainer$$ExternalSyntheticLambda" + i, lpparam.classLoader); if (c != null && BiConsumer.class.isAssignableFrom(c)) { deoptimizeMethod(c, "accept"); } } } catch (Throwable t) { XposedLogUtils.logE(TAG, t); } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/FreeFormCount.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class FreeFormCount : BaseHook() { override fun init() { val clazzMiuiFreeFormStackDisplayStrategy = loadClass("com.android.server.wm.MiuiFreeFormStackDisplayStrategy") // GetMaxMiuiFreeFormStackCount clazzMiuiFreeFormStackDisplayStrategy.methodFinder().filter { name in setOf( "getMaxMiuiFreeFormStackCount", "getMaxMiuiFreeFormStackCountForFlashBack" ) }.toList().createHooks { returnConstant(256) } // ShouldStopStartFreeform clazzMiuiFreeFormStackDisplayStrategy.methodFinder().first { name == "shouldStopStartFreeform" }.createHook { returnConstant(false) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/FreeformBubble.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class FreeformBubble extends BaseHook { Class mMiuiMultiWindowUtils; @Override public void init() { mMiuiMultiWindowUtils = findClassIfExists("android.util.MiuiMultiWindowUtils"); findAndHookMethod(mMiuiMultiWindowUtils, "multiFreeFormSupported", Context.class, XC_MethodReplacement.returnConstant(true)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/LocationSimulation.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; public class LocationSimulation extends BaseHook { Class mTelephonyManager; @Override public void init() { mTelephonyManager = findClassIfExists("android.telephony.TelephonyManager"); if (mTelephonyManager != null) { findAndHookMethod(mTelephonyManager, "getNetworkOperatorName", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedLogUtils.logI(TAG, "getNetworkOperatorName:" + param.getResult()); } }); findAndHookMethod(mTelephonyManager, "getSimOperatorName", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedLogUtils.logI(TAG, "getSimOperatorName:" + param.getResult()); } }); findAndHookMethod(mTelephonyManager, "getSimOperator", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedLogUtils.logI(TAG, "getSimOperator:" + param.getResult()); } }); findAndHookMethod(mTelephonyManager, "getNetworkOperator", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedLogUtils.logI(TAG, "getNetworkOperator:" + param.getResult()); } }); findAndHookMethod(mTelephonyManager, "getSimCountryIso", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedLogUtils.logI(TAG, "getSimCountryIso:" + param.getResult()); } }); findAndHookMethod(mTelephonyManager, "getNetworkCountryIso", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedLogUtils.logI(TAG, "getNetworkCountryIso:" + param.getResult()); } }); findAndHookMethod(mTelephonyManager, "getNeighboringCellInfo", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedLogUtils.logI(TAG, "getNeighboringCellInfo:" + param.getResult()); } }); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/MultiFreeFormSupported.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object MultiFreeFormSupported : BaseHook() { override fun init() { runCatching { if (!mPrefsMap.getBoolean("system_framework_freeform_recents_to_small_freeform")) { loadClass("android.util.MiuiMultiWindowUtils").methodFinder().first { name == "multiFreeFormSupported" }.createHook { before { val ex = Throwable() val stackTrace = ex.stackTrace var mResult = true for (i in stackTrace) { if (i.className == "com.android.server.wm.MiuiFreeFormGestureController\$FreeFormReceiver") { mResult = false break } } it.result = mResult } } XposedLogUtils.logI("Hook with recents_to_small_freeform success!") } else { loadClass("android.util.MiuiMultiWindowUtils").methodFinder().first { name == "multiFreeFormSupported" }.createHook { returnConstant(true) } XposedLogUtils.logI("Hook success!") } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/PackagePermissions.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.os.Build; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import de.robv.android.xposed.XposedHelpers; public class PackagePermissions extends BaseHook { private final ArrayList systemPackages = new ArrayList<>(); @Override public void init() { systemPackages.add(Helpers.mAppModulePkg); // Allow signature level permissions for module String PMSCls = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "com.android.server.pm.permission.PermissionManagerServiceImpl" : "com.android.server.pm.permission.PermissionManagerService"; // Allow signature level permissions for module hookAllMethods(PMSCls, "shouldGrantPermissionBySignature", new MethodHook() { @Override protected void before(MethodHookParam param) { String pkgName = (String) XposedHelpers.callMethod(param.args[0], "getPackageName"); if (systemPackages.contains(pkgName)) param.setResult(true); } }); hookAllMethodsSilently("com.android.server.pm.PackageManagerServiceUtils", "verifySignatures", new MethodHook() { @Override protected void before(MethodHookParam param) { String pkgName = (String) XposedHelpers.callMethod(param.args[0], "getName"); if (systemPackages.contains(pkgName)) param.setResult(true); } }); // Make module appear as system app String ActQueryService = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "com.android.server.pm.ComputerEngine" : "com.android.server.pm.PackageManagerService"; hookAllMethods(ActQueryService, "queryIntentActivitiesInternal", new MethodHook() { @Override @SuppressWarnings("unchecked") protected void after(MethodHookParam param) { if (param.args.length < 6) return; List infos = (List) param.getResult(); if (infos != null) { for (ResolveInfo info : infos) { if (info != null && info.activityInfo != null && systemPackages.contains(info.activityInfo.packageName)) { XposedHelpers.setObjectField(info, "system", true); } } } } }); findAndHookMethod("android.content.pm.ApplicationInfo", "isSystemApp", new MethodHook() { @Override protected void after(MethodHookParam param) { ApplicationInfo ai = (ApplicationInfo) param.thisObject; if (ai != null && systemPackages.contains(ai.packageName)) { param.setResult(true); } } }); findAndHookMethodSilently("android.content.pm.ApplicationInfo", "isSignedWithPlatformKey", new MethodHook() { @Override protected void after(MethodHookParam param) { ApplicationInfo ai = (ApplicationInfo) param.thisObject; if (ai != null && systemPackages.contains(ai.packageName)) { param.setResult(true); } } }); try { Class dpgpiClass = findClass("com.android.server.pm.MiuiDefaultPermissionGrantPolicy"); String[] MIUI_SYSTEM_APPS = (String[]) XposedHelpers.getStaticObjectField(dpgpiClass, "MIUI_SYSTEM_APPS"); ArrayList mySystemApps = new ArrayList<>(Arrays.asList(MIUI_SYSTEM_APPS)); mySystemApps.addAll(systemPackages); XposedHelpers.setStaticObjectField(dpgpiClass, "MIUI_SYSTEM_APPS", mySystemApps.toArray(new String[0])); } catch (Throwable t) { XposedLogUtils.logW(TAG, t); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/RemoveSmallWindowRestrictions.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework import android.content.Context import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.field import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object RemoveSmallWindowRestrictions : BaseHook() { private val mSettingsClass = loadClass("com.android.server.wm.WindowManagerService\$SettingsObserver") private val mWindowsUtilsClass = loadClass("android.util.MiuiMultiWindowUtils") private val mWindowsClass = loadClass("android.util.MiuiMultiWindowAdapter") override fun init() { try { loadClass("com.android.server.wm.ActivityTaskManagerService").methodFinder().first { name == "retrieveSettings" }.createHook { after { param -> param.thisObject.javaClass.field("mDevEnableNonResizableMultiWindow") .setBoolean(param.thisObject, true) } } } catch (e: Throwable) { XposedLogUtils.logI("Hook retrieveSettings failed by: $e") } try { mSettingsClass.methodFinder().filter { name == "updateDevEnableNonResizableMultiWindow" }.toList().createHooks { after { param -> val this0 = param.thisObject.javaClass.field("this\$0").get(param.thisObject) val mAtmService = this0.javaClass.field("mAtmService").get(this0) mAtmService.javaClass.field("mDevEnableNonResizableMultiWindow").setBoolean(mAtmService, true) } } } catch (e: Throwable) { XposedLogUtils.logI("Hook updateDevEnableNonResizableMultiWindow failed by: $e") } try { mSettingsClass.methodFinder().filter { name == "onChange" }.toList().createHooks { after { param -> val this0 = param.thisObject.javaClass.field("this\$0").get(param.thisObject) val mAtmService = this0.javaClass.field("mAtmService").get(this0) mAtmService.javaClass.field("mDevEnableNonResizableMultiWindow").setBoolean(mAtmService, true) } } } catch (e: Throwable) { XposedLogUtils.logI("Hook onChange failed by: $e") } try { mWindowsUtilsClass.methodFinder().first { name == "isForceResizeable" }.createHook { returnConstant(true) } } catch (e: Throwable) { XposedLogUtils.logI("Hook isForceResizeable failed by: $e") } // Author: LittleTurtle2333 try { loadClass("com.android.server.wm.Task").methodFinder().first { name == "isResizeable" }.createHook { returnConstant(true) } } catch (e: Throwable) { XposedLogUtils.logI("Hook isResizeable failed by: $e") } try { mWindowsClass.methodFinder().first { name == "getFreeformBlackList" }.createHook { returnConstant(mutableListOf()) } } catch (e: Throwable) { XposedLogUtils.logI("Hook getFreeformBlackList failed by: $e") } try { mWindowsClass.methodFinder().first { name == "getFreeformBlackListFromCloud" && parameterTypes[0] == Context::class.java }.createHook { returnConstant(mutableListOf()) } } catch (e: Throwable) { XposedLogUtils.logI("Hook getFreeformBlackListFromCloud failed by: $e") } try { mWindowsClass.methodFinder().first { name == "getStartFromFreeformBlackListFromCloud" }.createHook { returnConstant(mutableListOf()) } } catch (e: Throwable) { XposedLogUtils.logI("Hook getStartFromFreeformBlackListFromCloud failed by: $e") } try { mWindowsUtilsClass.methodFinder().first { name == "supportFreeform" }.createHook { returnConstant(true) } } catch (e: Throwable) { XposedLogUtils.logI("Hook supportFreeform failed by: $e") } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/ScreenRotation.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import android.content.Context; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class ScreenRotation extends BaseHook { @Override public void init() { findAndHookMethod("com.android.internal.view.RotationPolicy", "areAllRotationsAllowed", Context.class, XC_MethodReplacement.returnConstant(mPrefsMap.getBoolean("system_framework_screen_all_rotations"))); hookAllConstructors("com.android.server.wm.DisplayRotation", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.setIntField(param.thisObject, "mAllowAllRotations", mPrefsMap.getBoolean("system_framework_screen_all_rotations") ? 1 : 0); } }); } public static void initRes() { XposedInit.mResHook.setObjectReplacement("android", "bool", "config_allowAllRotations", mPrefsMap.getBoolean("system_framework_screen_all_rotations")); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/SpeedInstall.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; public class SpeedInstall extends BaseHook { @Override public void init() { hookAllMethods("android.content.pm.PackageInstaller", "isSupportedSpeedInstallV2", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/StickyFloatingWindows.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import android.annotation.SuppressLint; import android.app.ActivityOptions; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Rect; import android.provider.Settings; import android.util.Pair; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import de.robv.android.xposed.XposedHelpers; public class StickyFloatingWindows extends BaseHook { public static ConcurrentHashMap> fwApps = new ConcurrentHashMap<>(); @Override public void init() { final List fwBlackList = new ArrayList<>(); fwBlackList.add("com.miui.securitycenter"); fwBlackList.add("com.miui.home"); Class MiuiMultiWindowUtils = findClass("android.util.MiuiMultiWindowUtils"); hookAllMethods("com.android.server.wm.ActivityStarterInjector", "modifyLaunchActivityOptionIfNeed", new MethodHook() { @Override protected void after(MethodHookParam param) { if (param.args.length != 8) return; Intent intent = (Intent) param.args[5]; if (intent == null || intent.getComponent() == null) return; ActivityOptions options = (ActivityOptions) param.getResult(); int windowingMode = options == null ? -1 : (int) XposedHelpers.callMethod(options, "getLaunchWindowingMode"); String pkgName = intent.getComponent().getPackageName(); if (fwBlackList.contains(pkgName)) return; Context mContext; try { mContext = (Context) XposedHelpers.getObjectField(param.args[0], "mContext"); } catch (Throwable ignore) { mContext = (Context) XposedHelpers.getObjectField(XposedHelpers.getObjectField(param.args[0], "mService"), "mContext"); } if (windowingMode != 5 && fwApps.containsKey(pkgName)) { try { if (MiuiMultiWindowUtils == null) { XposedLogUtils.logI(TAG, "Cannot find MiuiMultiWindowUtils class"); return; } options = patchActivityOptions(mContext, options, pkgName, MiuiMultiWindowUtils); param.setResult(options); } catch (Throwable t) { XposedLogUtils.logW(TAG, "", t); } } else if (windowingMode == 5 && !fwApps.containsKey(pkgName)) { fwApps.put(pkgName, new Pair<>(0f, null)); storeFwAppsInSetting(mContext); } } }); hookAllMethods("com.android.server.wm.ActivityTaskSupervisor", "startActivityFromRecents", new MethodHook() { @Override protected void after(MethodHookParam param) { Object safeOptions = param.args[3]; ActivityOptions options = (ActivityOptions) XposedHelpers.callMethod(safeOptions, "getOptions", param.thisObject); int windowingMode = options == null ? -1 : (int) XposedHelpers.callMethod(options, "getLaunchWindowingMode"); String pkgName = getTaskPackageName(param.thisObject, (int) param.args[2], options); if (fwBlackList.contains(pkgName)) return; if (windowingMode == 5 && pkgName != null) { fwApps.put(pkgName, new Pair<>(0f, null)); Context mContext = (Context) XposedHelpers.getObjectField(XposedHelpers.getObjectField(param.thisObject, "mService"), "mContext"); storeFwAppsInSetting(mContext); } } @Override protected void before(MethodHookParam param) { Object safeOptions = param.args[3]; ActivityOptions options = (ActivityOptions) XposedHelpers.callMethod(safeOptions, "getOptions", param.thisObject); int windowingMode = options == null ? -1 : (int) XposedHelpers.callMethod(options, "getLaunchWindowingMode"); String pkgName = getTaskPackageName(param.thisObject, (int) param.args[2], options); if (fwBlackList.contains(pkgName)) return; if (windowingMode != 5 && fwApps.containsKey(pkgName)) { Context mContext = (Context) XposedHelpers.getObjectField(XposedHelpers.getObjectField(param.thisObject, "mService"), "mContext"); options = patchActivityOptions(mContext, options, pkgName, MiuiMultiWindowUtils); XposedHelpers.setObjectField(safeOptions, "mOriginalOptions", options); param.args[3] = safeOptions; Intent intent = new Intent(ACTION_PREFIX + "dismissRecentsWhenFreeWindowOpen"); intent.putExtra("package", pkgName); mContext.sendBroadcast(intent); } } }); findAndHookMethod("com.android.server.wm.MiuiFreeFormGestureController$FreeFormReceiver", "onReceive", Context.class, Intent.class, new MethodHook() { @Override protected void before(MethodHookParam param) { Intent intent = (Intent) param.args[1]; String action = intent.getAction(); if (action.equals("miui.intent.action_launch_fullscreen_from_freeform")) { Object parentThis = XposedHelpers.getSurroundingThis(param.thisObject); XposedHelpers.setAdditionalInstanceField(parentThis, "skipFreeFormStateClear", true); } } }); hookAllMethods("com.android.server.wm.MiuiFreeFormGestureController", "notifyFullScreenWidnowModeStart", new MethodHook() { @Override protected void before(MethodHookParam param) { if (param.args.length != 3) return; String pkgName = (String) XposedHelpers.callMethod(param.args[1], "getStackPackageName"); Object skipClear = XposedHelpers.getAdditionalInstanceField(param.thisObject, "skipFreeFormStateClear"); boolean skipFreeFormStateClear = false; if (skipClear != null) { skipFreeFormStateClear = (boolean) skipClear; } if (!skipFreeFormStateClear) { if (fwBlackList.contains(pkgName)) return; if (fwApps.remove(pkgName) != null) { storeFwAppsInSetting((Context) XposedHelpers.getObjectField(XposedHelpers.getObjectField(param.thisObject, "mService"), "mContext")); } } else { XposedHelpers.setAdditionalInstanceField(param.thisObject, "skipFreeFormStateClear", false); } } }); hookAllMethods("com.android.server.wm.ActivityTaskManagerService", "launchSmallFreeFormWindow", new MethodHook() { @Override protected void after(MethodHookParam param) { Object taskId = XposedHelpers.getObjectField(param.args[0], "taskId"); Object mMiuiFreeFormManagerService = XposedHelpers.getObjectField(param.thisObject, "mMiuiFreeFormManagerService"); Object miuiFreeFormActivityStack = XposedHelpers.callMethod(mMiuiFreeFormManagerService, "getMiuiFreeFormActivityStack", taskId); String pkgName = (String) XposedHelpers.callMethod(miuiFreeFormActivityStack, "getStackPackageName"); if (fwBlackList.contains(pkgName)) return; if (!fwApps.containsKey(pkgName)) { fwApps.put(pkgName, new Pair<>(0f, null)); Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); storeFwAppsInSetting(mContext); } } }); findAndHookMethod("com.android.server.wm.ActivityTaskManagerService", "onSystemReady", new MethodHook() { @SuppressLint("UnspecifiedRegisterReceiverFlag") @Override protected void after(MethodHookParam param) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); restoreFwAppsInSetting(mContext); Class MiuiMultiWindowAdapter = findClass("android.util.MiuiMultiWindowAdapter", lpparam.classLoader); List blackList = (List) XposedHelpers.getStaticObjectField(MiuiMultiWindowAdapter, "FREEFORM_BLACK_LIST"); blackList.clear(); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals("miui.intent.action_launch_fullscreen_from_freeform")) { XposedHelpers.setAdditionalInstanceField(param.thisObject, "skipFreeFormStateClear", true); } } }, new IntentFilter("miui.intent.action_launch_fullscreen_from_freeform")); } }); hookAllMethods("com.android.server.wm.ActivityTaskManagerService", "resizeTask", new MethodHook() { @Override protected void before(MethodHookParam param) { String pkgName = getTaskPackageName(param.thisObject, (int) param.args[0]); if (pkgName != null) { Object skipClear = XposedHelpers.getAdditionalInstanceField(param.thisObject, "skipFreeFormStateClear"); boolean skipFreeFormStateClear = false; if (skipClear != null) { skipFreeFormStateClear = (boolean) skipClear; } if (skipFreeFormStateClear) { XposedHelpers.setAdditionalInstanceField(param.thisObject, "skipFreeFormStateClear", false); } else { if (fwBlackList.contains(pkgName)) return; Object mMiuiFreeFormManagerService = XposedHelpers.getObjectField(param.thisObject, "mMiuiFreeFormManagerService"); Object miuiFreeFormActivityStack = XposedHelpers.callMethod(mMiuiFreeFormManagerService, "getMiuiFreeFormActivityStack", param.args[0]); if (fwApps.containsKey(pkgName)) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); float sScale = (float) XposedHelpers.callMethod(miuiFreeFormActivityStack, "getFreeFormScale"); fwApps.put(pkgName, new Pair<>(sScale, new Rect((Rect) param.args[1]))); storeFwAppsInSetting(mContext); } } } } }); } public static String getTaskPackageName(Object thisObject, int taskId) { return getTaskPackageName(thisObject, taskId, false, null); } public static String getTaskPackageName(Object thisObject, int taskId, ActivityOptions options) { return getTaskPackageName(thisObject, taskId, true, options); } public static String getTaskPackageName(Object thisObject, int taskId, boolean withOptions, ActivityOptions options) { Object mRootWindowContainer = XposedHelpers.getObjectField(thisObject, "mRootWindowContainer"); if (mRootWindowContainer == null) return null; Object task = withOptions ? XposedHelpers.callMethod(mRootWindowContainer, "anyTaskForId", taskId, 2, options, true) : XposedHelpers.callMethod(mRootWindowContainer, "anyTaskForId", taskId, 0); if (task == null) return null; Intent intent = (Intent) XposedHelpers.getObjectField(task, "intent"); return intent == null ? null : intent.getComponent().getPackageName(); } public static String serializeFwApps() { StringBuilder data = new StringBuilder(); for (Map.Entry> entry : fwApps.entrySet()) { Pair val = entry.getValue(); data.append(entry.getKey()); data.append(":"); data.append(val.first); data.append(":"); data.append(val.second == null ? "-" : val.second.flattenToString()); data.append("|"); } return data.toString().replaceFirst("\\|$", ""); } public static void unserializeFwApps(String data) { fwApps.clear(); if (data == null || data.isEmpty()) return; String[] dataArr = data.split("\\|"); for (String appData : dataArr) { if ("".equals(appData)) continue; String[] appDataArr = appData.split(":"); fwApps.put(appDataArr[0], new Pair<>(Float.parseFloat(appDataArr[1]), "-".equals(appDataArr[2]) ? null : Rect.unflattenFromString(appDataArr[2]))); } } public static void storeFwAppsInSetting(Context context) { Settings.Global.putString(context.getContentResolver(), Helpers.mAppModulePkg + ".fw.apps", serializeFwApps()); } public static void restoreFwAppsInSetting(Context context) { unserializeFwApps(Settings.Global.getString(context.getContentResolver(), Helpers.mAppModulePkg + ".fw.apps")); } private static ActivityOptions patchActivityOptions(Context mContext, ActivityOptions options, String pkgName, Class MiuiMultiWindowUtils) { if (options == null) options = ActivityOptions.makeBasic(); XposedHelpers.callMethod(options, "setLaunchWindowingMode", 5); XposedHelpers.callMethod(options, "setMiuiConfigFlag", 2); Float scale; Rect rect; Pair values = fwApps.get(pkgName); if (values == null || values.first == 0f || values.second == null) { scale = 0.7f; rect = (Rect) XposedHelpers.callStaticMethod(MiuiMultiWindowUtils, "getFreeformRect", mContext); } else { scale = values.first; rect = values.second; } options.setLaunchBounds(rect); try { Object injector = XposedHelpers.callMethod(options, "getActivityOptionsInjector"); XposedHelpers.callMethod(injector, "setFreeformScale", scale); } catch (Throwable ignore) { } return options; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/ThemeProvider.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.Log import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XC_MethodHook import miui.drm.DrmManager import miui.drm.ThemeReceiver class ThemeProvider : BaseHook() { override fun init() { var hook: List? = null try { ThemeReceiver::class.java.methodFinder().filterByName("validateTheme").first().createHook { before { hook = DrmManager::class.java.methodFinder().filterByName("isLegal").toList().createHooks { returnConstant(DrmManager.DrmResult.DRM_SUCCESS) } } after { hook?.forEach { it.unhook() } } } } catch (t: Throwable) { Log.ex(t) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/ThermalBrightness.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedHelpers; public class ThermalBrightness extends BaseHook { public final String displayPowerControllerImpl = "com.android.server.display.DisplayPowerControllerImpl"; public final String automaticBrightnessControllerImpl = "com.android.server.display.AutomaticBrightnessControllerImpl"; public final String thermalBrightnessController = "com.android.server.display.ThermalBrightnessController"; public final String temperatureController = "com.android.server.display.TemperatureController"; @Override public void init() { try { XposedHelpers.findClass(displayPowerControllerImpl, lpparam.classLoader); findAndHookConstructor(displayPowerControllerImpl, new MethodHook() { @Override protected void after(MethodHookParam param) { setDeclaredField(param, "SUPPORT_TEMEPERATURE_CONTROL", false); setDeclaredField(param, "mThermalBrightnessControlAvailable", false); setDeclaredField(param, "mApplyThermalBrightnessRate", false); } } ); } catch (XposedHelpers.ClassNotFoundError e) { XposedLogUtils.logE(TAG, "No found class: " + e); } try { XposedHelpers.findClass(automaticBrightnessControllerImpl, lpparam.classLoader); findAndHookConstructor(automaticBrightnessControllerImpl, new MethodHook() { @Override protected void after(MethodHookParam param) { setDeclaredField(param, "SUPPORT_TEMEPERATURE_CONTROL", false); } } ); } catch (XposedHelpers.ClassNotFoundError e) { XposedLogUtils.logE(TAG, "No found class: " + e); } try { findClassIfExists(temperatureController).getDeclaredMethod("updateTemperature"); findAndHookMethod(temperatureController, "updateTemperature", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(null); } } ); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have updateTemperature: " + e); } /*hookAllMethods("com.android.server.display.DisplayPowerControllerImpl", "adjustBrightnessByThermal", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(param.args[0]); } } );*/ try { findClassIfExists(displayPowerControllerImpl).getDeclaredMethod("updateThermalBrightness", float.class); findAndHookMethod(displayPowerControllerImpl, "updateThermalBrightness", float.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(null); } } ); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have updateThermalBrightness: " + e); } try { findClassIfExists(thermalBrightnessController).getDeclaredMethod("updateThermalBrightnessIfNeeded"); findAndHookMethod(thermalBrightnessController, "updateThermalBrightnessIfNeeded", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(false); } } ); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have updateThermalBrightnessIfNeeded: " + e); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/UseOriginalAnimation.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UseOriginalAnimation extends BaseHook { @Override public void init() { hookAllMethods("com.android.server.wm.AppTransitionInjector", "createActivityOpenCloseTransition", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(null); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/VolumeDefaultStream.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import android.content.Context; import android.os.Handler; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.PrefsUtils; import de.robv.android.xposed.XposedHelpers; public class VolumeDefaultStream extends BaseHook { Class mAudioService; @Override public void init() { mAudioService = findClassIfExists("com.android.server.audio.AudioService"); findAndHookMethod(mAudioService, "getActiveStreamType", int.class, new MethodHook() { @Override protected void before(MethodHookParam param) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); Handler mHandler = new Handler(mContext.getMainLooper()); new PrefsUtils.SharedPrefsObserver(mContext, mHandler, "prefs_key_system_framework_default_volume_stream", "0") { @Override public void onChange(String name, String defValue) { mPrefsMap.put(name, PrefsUtils.getSharedStringPrefs(mContext, name, defValue)); } }; int mDefaultVolumeStream = mPrefsMap.getStringAsInt("system_framework_default_volume_stream", 0); if (mDefaultVolumeStream > 0) { param.setResult(mDefaultVolumeStream); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/VolumeDisableSafe.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class VolumeDisableSafe extends BaseHook { Class mAudioService; @Override public void init() { mAudioService = findClassIfExists("com.android.server.audio.AudioService"); returnIntConstant(mAudioService, "safeMediaVolumeIndex"); } private void returnIntConstant(Class cls, String methodName) { hookAllMethods(cls, methodName, XC_MethodReplacement.returnConstant(2147483646)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/VolumeFirstPress.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import android.media.AudioManager; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class VolumeFirstPress extends BaseHook { Class mVolumeController; @Override public void init() { mVolumeController = findClassIfExists("com.android.server.audio.AudioService$VolumeController"); findAndHookMethod(mVolumeController, "suppressAdjustment", int.class, int.class, boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { int streamType = (int) param.args[0]; if (streamType != AudioManager.STREAM_MUSIC) return; boolean isMuteAdjust = (boolean) param.args[2]; if (isMuteAdjust) return; Object mController = XposedHelpers.getObjectField(param.thisObject, "mController"); if (mController == null) return; param.setResult(false); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/VolumeMediaSteps.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class VolumeMediaSteps : BaseHook() { override fun init() { val mediaStepsSwitch = mPrefsMap.getInt("system_framework_volume_media_steps", 15) > 15 val mediaSteps = mPrefsMap.getInt("system_framework_volume_media_steps", 15) loadClass("android.os.SystemProperties").methodFinder().first { name == "getInt" && returnType == Int::class.java }.createHook { before { when (it.args[0] as String) { "ro.config.media_vol_steps" -> if (mediaStepsSwitch) it.result = mediaSteps } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/VolumeSeparateControl.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidT; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.os.Build; import android.provider.Settings; import android.util.SparseIntArray; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.Set; import de.robv.android.xposed.XposedHelpers; public class VolumeSeparateControl extends BaseHook { Class mAudioService; @Override public void init() { mAudioService = findClassIfExists("com.android.server.audio.AudioService"); findAndHookMethod(mAudioService, "updateStreamVolumeAlias", boolean.class, String.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { int[] mStreamVolumeAlias = (int[]) (isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? XposedHelpers.getStaticObjectField(mAudioService, "mStreamVolumeAlias") : XposedHelpers.getObjectField(param.thisObject, "mStreamVolumeAlias")); mStreamVolumeAlias[1] = 1; mStreamVolumeAlias[5] = 5; if (isAndroidT()) { XposedHelpers.setStaticObjectField(mAudioService, "mStreamVolumeAlias", mStreamVolumeAlias); } else { XposedHelpers.setObjectField(param.thisObject, "mStreamVolumeAlias", mStreamVolumeAlias); } } }); findAndHookMethod("com.android.server.audio.AudioService$VolumeStreamState", "readSettings", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { int mStreamType = XposedHelpers.getIntField(param.thisObject, "mStreamType"); if (mStreamType != 1) return; synchronized (param.method.getDeclaringClass()) { Class audioSystem = XposedHelpers.findClassIfExists("android.media.AudioSystem", lpparam.classLoader); Set DEVICE_OUT_ALL = (Set) XposedHelpers.getStaticObjectField(audioSystem, "DEVICE_OUT_ALL_SET"); int DEVICE_OUT_DEFAULT = XposedHelpers.getStaticIntField(audioSystem, "DEVICE_OUT_DEFAULT"); int[] DEFAULT_STREAM_VOLUME = (int[]) XposedHelpers.getStaticObjectField(audioSystem, "DEFAULT_STREAM_VOLUME"); Set remainingDevices = DEVICE_OUT_ALL; Object mContentResolver = XposedHelpers.getObjectField(XposedHelpers.getSurroundingThis(param.thisObject), "mContentResolver"); SparseIntArray mIndexMap = (SparseIntArray) XposedHelpers.getObjectField(param.thisObject, "mIndexMap"); for (Integer deviceType : remainingDevices) { int device = deviceType; String name = (String) XposedHelpers.callMethod(param.thisObject, "getSettingNameForDevice", device); int index = (int) XposedHelpers.callStaticMethod(Settings.System.class, "getIntForUser", mContentResolver, name, device == DEVICE_OUT_DEFAULT ? DEFAULT_STREAM_VOLUME[mStreamType] : -1, -2); if (index != -1) { mIndexMap.put(device, (int) XposedHelpers.callMethod(param.thisObject, "getValidIndex", 10 * index, true)); } } XposedHelpers.setObjectField(param.thisObject, "mIndexMap", mIndexMap); } param.setResult(null); } }); findAndHookMethodSilently(mAudioService, "shouldZenMuteStream", int.class, new MethodHook() { protected void after(MethodHookParam param) throws Throwable { int mStreamType = (int) param.args[0]; if (mStreamType == 5 && !(boolean) param.getResult()) { int mZenMode = (int) XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "mNm"), "getZenMode"); if (mZenMode == 1) param.setResult(true); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/VolumeSteps.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class VolumeSteps extends BaseHook { Class mAudioService; @Override public void init() { mAudioService = findClass("com.android.server.audio.AudioService"); findAndHookMethod(mAudioService, "createStreamStates", new MethodHook() { @Override protected void before(MethodHookParam param) { int[] maxStreamVolume = (int[]) XposedHelpers.getStaticObjectField(mAudioService, "MAX_STREAM_VOLUME"); int mult = mPrefsMap.getInt("system_framework_volume_steps", 0); if (mult <= 0) return; for (int i = 0; i < maxStreamVolume.length; i++) maxStreamVolume[i] = Math.round(maxStreamVolume[i] * mult / 100.0f); XposedHelpers.setStaticObjectField(mAudioService, "MAX_STREAM_VOLUME", maxStreamVolume); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/corepatch/BypassSignCheckForT.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.corepatch import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object BypassSignCheckForT : BaseHook() { override fun init() { try { hookAllMethods("android.util.apk.ApkSignatureVerifier", "getMinimumSignatureSchemeVersionForTargetSdk", object : MethodHook() { override fun after(param: MethodHookParam?) { param?.result = 1 } }) } catch (e: Throwable) { XposedLogUtils.logE(TAG, e) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/corepatch/CorePatchForR.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.corepatch; import static com.sevtinge.cemiuiler.module.app.SystemFrameworkForCorePatch.TAG; import static de.robv.android.xposed.XposedHelpers.findClassIfExists; import static de.robv.android.xposed.XposedHelpers.findMethodExactIfExists; import android.app.AndroidAppHelper; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.util.Log; import com.sevtinge.cemiuiler.BuildConfig; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.PrefsUtils; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.zip.ZipEntry; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.IXposedHookZygoteInit; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XSharedPreferences; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class CorePatchForR extends XposedHelper implements IXposedHookLoadPackage, IXposedHookZygoteInit { private final static Method deoptimizeMethod; private static final boolean isNotReleaseVersion = !BuildConfig.BUILD_TYPE.contains("release"); static { Method m = null; try { m = XposedBridge.class.getDeclaredMethod("deoptimizeMethod", Member.class); } catch (Throwable t) { XposedBridge.log("[E" + TAG + ": " + Log.getStackTraceString(t)); } deoptimizeMethod = m; } static void deoptimizeMethod(Class c, String n) throws InvocationTargetException, IllegalAccessException { for (Method m : c.getDeclaredMethods()) { if (deoptimizeMethod != null && m.getName().equals(n)) { deoptimizeMethod.invoke(null, m); if (isNotReleaseVersion) XposedBridge.log("[D" + TAG + ": Deoptimized " + m.getName()); } } } final XSharedPreferences prefs = new XSharedPreferences(Helpers.mAppModulePkg, PrefsUtils.mPrefsName); @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws IllegalAccessException, InvocationTargetException, InstantiationException { if (isNotReleaseVersion) { XposedBridge.log("[D" + TAG + ": downgrade=" + prefs.getBoolean("prefs_key_system_framework_core_patch_downgr", true)); XposedBridge.log("[D" + TAG + ": authcreak=" + prefs.getBoolean("prefs_key_system_framework_core_patch_auth_creak", true)); XposedBridge.log("[D" + TAG + ": digestCreak=" + prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true)); XposedBridge.log("[D" + TAG + ": UsePreSig=" + prefs.getBoolean("prefs_key_system_framework_core_patch_use_pre_signature", false)); XposedBridge.log("[D" + TAG + ": enhancedMode=" + prefs.getBoolean("prefs_key_system_framework_core_patch_enhanced_mode", false)); } var pmService = findClassIfExists("com.android.server.pm.PackageManagerService", loadPackageParam.classLoader); if (pmService != null) { var checkDowngrade = findMethodExactIfExists(pmService, "checkDowngrade", "com.android.server.pm.parsing.pkg.AndroidPackage", "android.content.pm.PackageInfoLite"); if (checkDowngrade != null) { // 允许降级 XposedBridge.hookMethod(checkDowngrade, new ReturnConstant(prefs, "prefs_key_system_framework_core_patch_downgr", null)); } } // apk内文件修改后 digest校验会失败 hookAllMethods("android.util.jar.StrictJarVerifier", loadPackageParam.classLoader, "verifyMessageDigest", new ReturnConstant(prefs, "prefs_key_system_framework_core_patch_auth_creak", true)); hookAllMethods("android.util.jar.StrictJarVerifier", loadPackageParam.classLoader, "verify", new ReturnConstant(prefs, "prefs_key_system_framework_core_patch_auth_creak", true)); hookAllMethods("java.security.MessageDigest", loadPackageParam.classLoader, "isEqual", new ReturnConstant(prefs, "prefs_key_system_framework_core_patch_auth_creak", true)); // Targeting R+ (version " + Build.VERSION_CODES.R + " and above) requires" // + " the resources.arsc of installed APKs to be stored uncompressed" // + " and aligned on a 4-byte boundary // target >=30 的情况下 resources.arsc 必须是未压缩的且4K对齐 hookAllMethods("android.content.res.AssetManager", loadPackageParam.classLoader, "containsAllocatedTable", new ReturnConstant(prefs, "prefs_key_system_framework_core_patch_auth_creak", false)); // No signature found in package of version " + minSignatureSchemeVersion // + " or newer for package " + apkPath findAndHookMethod("android.util.apk.ApkSignatureVerifier", loadPackageParam.classLoader, "getMinimumSignatureSchemeVersionForTargetSdk", int.class, new ReturnConstant(prefs, "prefs_key_system_framework_core_patch_auth_creak", 0)); var apkVerifierClass = XposedHelpers.findClassIfExists("com.android.apksig.ApkVerifier", loadPackageParam.classLoader); if (apkVerifierClass != null) { findAndHookMethod(apkVerifierClass, "getMinimumSignatureSchemeVersionForTargetSdk", loadPackageParam.classLoader, int.class, new ReturnConstant(prefs, "prefs_key_system_framework_core_patch_auth_creak", 0)); } // Package " + packageName + " signatures do not match previously installed version; ignoring!" // public boolean checkCapability(String sha256String, @CertCapabilities int flags) { // public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) hookAllMethods("android.content.pm.PackageParser", loadPackageParam.classLoader, "checkCapability", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { // Don't handle PERMISSION (grant SIGNATURE permissions to pkgs with this cert) // Or applications will have all privileged permissions // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/content/pm/PackageParser.java;l=5947?q=CertCapabilities if (prefs.getBoolean("prefs_key_system_framework_core_patch_auth_creak", true)) { if ((Integer) param.args[1] != 4) { param.setResult(true); } } } }); // 当verifyV1Signature抛出转换异常时,替换一个签名作为返回值 // 如果用户已安装apk,并且其定义了私有权限,则安装时会因签名与模块内硬编码的不一致而被拒绝。尝试从待安装apk中获取签名。如果其中apk的签名和已安装的一致(只动了内容)就没有问题。此策略可能有潜在的安全隐患。 Class pkc = XposedHelpers.findClass("sun.security.pkcs.PKCS7", loadPackageParam.classLoader); Constructor constructor = XposedHelpers.findConstructorExact(pkc, byte[].class); constructor.setAccessible(true); Class ASV = XposedHelpers.findClass("android.util.apk.ApkSignatureVerifier", loadPackageParam.classLoader); Class sJarClass = XposedHelpers.findClass("android.util.jar.StrictJarFile", loadPackageParam.classLoader); Constructor constructorExact = XposedHelpers.findConstructorExact(sJarClass, String.class, boolean.class, boolean.class); constructorExact.setAccessible(true); Class signingDetails = getSigningDetails(loadPackageParam.classLoader); Constructor findConstructorExact = XposedHelpers.findConstructorExact(signingDetails, Signature[].class, Integer.TYPE); findConstructorExact.setAccessible(true); Class packageParserException = XposedHelpers.findClass("android.content.pm.PackageParser.PackageParserException", loadPackageParam.classLoader); Field error = XposedHelpers.findField(packageParserException, "error"); error.setAccessible(true); Object[] signingDetailsArgs = new Object[2]; signingDetailsArgs[1] = 1; Class parseResult = findClassIfExists("android.content.pm.parsing.result.ParseResult", loadPackageParam.classLoader); hookAllMethods("android.util.jar.StrictJarVerifier", loadPackageParam.classLoader, "verifyBytes", new XC_MethodHook() { public void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); if (prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true)) { if (!prefs.getBoolean("prefs_key_system_framework_core_patch_use_pre_signature", false)) { final Object block = constructor.newInstance(param.args[0]); Object[] infos = (Object[]) XposedHelpers.callMethod(block, "getSignerInfos"); Object info = infos[0]; List verifiedSignerCertChain = (List) XposedHelpers.callMethod(info, "getCertificateChain", block); param.setResult(verifiedSignerCertChain.toArray( new X509Certificate[0])); } } } }); hookAllMethods("android.util.apk.ApkSignatureVerifier", loadPackageParam.classLoader, "verifyV1Signature", new XC_MethodHook() { public void afterHookedMethod(MethodHookParam methodHookParam) throws Throwable { if (prefs.getBoolean("prefs_key_system_framework_core_patch_auth_creak", true)) { Throwable throwable = methodHookParam.getThrowable(); Integer parseErr = null; if (parseResult != null && ((Method) methodHookParam.method).getReturnType() == parseResult) { Object result = methodHookParam.getResult(); if ((boolean) XposedHelpers.callMethod(result, "isError")) { parseErr = (int) XposedHelpers.callMethod(result, "getErrorCode"); } } if (throwable != null || parseErr != null) { Signature[] lastSigs = null; try { if (prefs.getBoolean("prefs_key_system_framework_core_patch_use_pre_signature", false)) { PackageManager PM = AndroidAppHelper.currentApplication().getPackageManager(); if (PM == null) { XposedBridge.log("[E" + TAG +"[" + BuildConfig.APPLICATION_ID + "] Cannot get the Package Manager... Are you using MiUI?"); } else { PackageInfo pI; if (parseErr != null) { pI = PM.getPackageArchiveInfo((String) methodHookParam.args[1], 0); } else { pI = PM.getPackageArchiveInfo((String) methodHookParam.args[0], 0); } PackageInfo InstpI = PM.getPackageInfo(pI.packageName, PackageManager.GET_SIGNATURES); lastSigs = InstpI.signatures; } } } catch (Throwable ignored) { } try { if (lastSigs == null && prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true)) { final Object origJarFile = constructorExact.newInstance(methodHookParam.args[parseErr == null ? 0 : 1], true, false); final ZipEntry manifestEntry = (ZipEntry) XposedHelpers.callMethod(origJarFile, "findEntry", "AndroidManifest.xml"); final Certificate[][] lastCerts; if (parseErr != null) { lastCerts = (Certificate[][]) XposedHelpers.callMethod(XposedHelpers.callStaticMethod(ASV, "loadCertificates", methodHookParam.args[0], origJarFile, manifestEntry), "getResult"); } else { lastCerts = (Certificate[][]) XposedHelpers.callStaticMethod(ASV, "loadCertificates", origJarFile, manifestEntry); } lastSigs = (Signature[]) XposedHelpers.callStaticMethod(ASV, "convertToSignatures", (Object) lastCerts); } } catch (Throwable ignored) { } if (lastSigs != null) { signingDetailsArgs[0] = lastSigs; } else { signingDetailsArgs[0] = new Signature[]{new Signature(SIGNATURE)}; } Object newInstance = findConstructorExact.newInstance(signingDetailsArgs); // 修复 java.lang.ClassCastException: Cannot cast android.content.pm.PackageParser$SigningDetails to android.util.apk.ApkSignatureVerifier$SigningDetailsWithDigests Class signingDetailsWithDigests = findClassIfExists("android.util.apk.ApkSignatureVerifier.SigningDetailsWithDigests", loadPackageParam.classLoader); if (signingDetailsWithDigests != null) { Constructor signingDetailsWithDigestsConstructorExact = XposedHelpers.findConstructorExact(signingDetailsWithDigests, signingDetails, Map.class); signingDetailsWithDigestsConstructorExact.setAccessible(true); newInstance = signingDetailsWithDigestsConstructorExact.newInstance(newInstance, null); } if (throwable != null) { Throwable cause = throwable.getCause(); if (throwable.getClass() == packageParserException) { if (error.getInt(throwable) == -103) { methodHookParam.setResult(newInstance); } } if (cause != null && cause.getClass() == packageParserException) { if (error.getInt(cause) == -103) { methodHookParam.setResult(newInstance); } } } if (parseErr != null && parseErr == -103) { Object input = methodHookParam.args[0]; XposedHelpers.callMethod(input, "reset"); methodHookParam.setResult(XposedHelpers.callMethod(input, "success", newInstance)); } } } } }); // New package has a different signature // 处理覆盖安装但签名不一致 hookAllMethods(signingDetails, "checkCapability", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { // Don't handle PERMISSION (grant SIGNATURE permissions to pkgs with this cert) // Or applications will have all privileged permissions // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/content/pm/PackageParser.java;l=5947?q=CertCapabilities if (((Integer) param.args[1] != 4) && prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true)) { param.setResult(true); } } }); // if app is system app, allow to use hidden api, even if app not using a system signature findAndHookMethod("android.content.pm.ApplicationInfo", loadPackageParam.classLoader, "isPackageWhitelistedForHiddenApis", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); if (prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true)) { ApplicationInfo info = (ApplicationInfo) param.thisObject; if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0 || (info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { param.setResult(true); } } } }); var utilClass = findClass("com.android.server.pm.PackageManagerServiceUtils", loadPackageParam.classLoader); if (utilClass != null) { try { deoptimizeMethod(utilClass, "verifySignatures"); } catch (Throwable e) { XposedBridge.log("[E" + TAG + ": deoptimizing failed" + Log.getStackTraceString(e)); } } var keySetManagerClass = findClass("com.android.server.pm.KeySetManagerService", loadPackageParam.classLoader); if (keySetManagerClass != null) { var shouldBypass = new ThreadLocal(); hookAllMethods(keySetManagerClass, "shouldCheckUpgradeKeySetLocked", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) { if (prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true) && Arrays.stream(Thread.currentThread().getStackTrace()).anyMatch((o) -> "preparePackageLI".equals(o.getMethodName()))) { shouldBypass.set(true); param.setResult(true); } else { shouldBypass.set(false); } } }); hookAllMethods(keySetManagerClass, "checkUpgradeKeySetLocked", new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) { if (prefs.getBoolean("digestCreak", true) && shouldBypass.get()) { param.setResult(true); } } }); } } Class getSigningDetails(ClassLoader classLoader) { return XposedHelpers.findClass("android.content.pm.PackageParser.SigningDetails", classLoader); } @Override public void initZygote(StartupParam startupParam) { hookAllMethods("android.content.pm.PackageParser", null, "getApkSigningVersion", XC_MethodReplacement.returnConstant(1)); hookAllConstructors("android.util.jar.StrictJarVerifier", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (prefs.getBoolean("prefs_key_system_framework_core_patch_enhanced_mode", false)) { super.beforeHookedMethod(param); param.args[3] = Boolean.FALSE; } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/corepatch/CorePatchForS.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.corepatch; import static de.robv.android.xposed.XposedBridge.hookMethod; import java.lang.reflect.InvocationTargetException; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class CorePatchForS extends CorePatchForR { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws IllegalAccessException, InvocationTargetException, InstantiationException { super.handleLoadPackage(loadPackageParam); var pmService = XposedHelpers.findClassIfExists("com.android.server.pm.PackageManagerService", loadPackageParam.classLoader); if (pmService != null) { var doesSignatureMatchForPermissions = XposedHelpers.findMethodExactIfExists(pmService, "doesSignatureMatchForPermissions", String.class, "com.android.server.pm.parsing.pkg.ParsedPackage", int.class); if (doesSignatureMatchForPermissions != null) { hookMethod(doesSignatureMatchForPermissions, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) { if (prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true) && prefs.getBoolean("prefs_key_system_framework_core_patch_use_pre_signature", false)) { //If we decide to crack this then at least make sure they are same apks, avoid another one that tries to impersonate. if (param.getResult().equals(false)) { String pPname = (String) XposedHelpers.callMethod(param.args[1], "getPackageName"); if (pPname.contentEquals((String) param.args[0])) { param.setResult(true); } } } } }); } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/corepatch/CorePatchForT.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.corepatch; import java.lang.reflect.InvocationTargetException; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class CorePatchForT extends CorePatchForS { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws IllegalAccessException, InvocationTargetException, InstantiationException { super.handleLoadPackage(loadPackageParam); var checkDowngrade = XposedHelpers.findMethodExactIfExists("com.android.server.pm.PackageManagerServiceUtils", loadPackageParam.classLoader, "checkDowngrade", "com.android.server.pm.parsing.pkg.AndroidPackage", "android.content.pm.PackageInfoLite"); if (checkDowngrade != null) { XposedBridge.hookMethod(checkDowngrade, new ReturnConstant(prefs, "prefs_key_system_framework_core_patch_downgr", null)); } Class signingDetails = getSigningDetails(loadPackageParam.classLoader); // New package has a different signature // 处理覆盖安装但签名不一致 hookAllMethods(signingDetails, "checkCapability", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { // Don't handle PERMISSION (grant SIGNATURE permissions to pkgs with this cert) // Or applications will have all privileged permissions // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/content/pm/PackageParser.java;l=5947?q=CertCapabilities if (prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true)) { if ((Integer) param.args[1] != 4) { param.setResult(true); } } } }); // Package " + packageName + " signatures do not match previously installed version; ignoring!" // public boolean checkCapability(String sha256String, @CertCapabilities int flags) { // public boolean checkCapability(SigningDetails oldDetails, @CertCapabilities int flags) hookAllMethods("android.content.pm.PackageParser", loadPackageParam.classLoader, "checkCapability", new XC_MethodHook() { @Override protected void beforeHookedMethod(MethodHookParam param) { // Don't handle PERMISSION (grant SIGNATURE permissions to pkgs with this cert) // Or applications will have all privileged permissions // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/content/pm/PackageParser.java;l=5947?q=CertCapabilities if (prefs.getBoolean("prefs_key_system_framework_core_patch_auth_creak", true)) { if ((Integer) param.args[1] != 4) { param.setResult(true); } } } }); findAndHookMethod("com.android.server.pm.InstallPackageHelper", loadPackageParam.classLoader, "doesSignatureMatchForPermissions", String.class, "com.android.server.pm.parsing.pkg.ParsedPackage", int.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) { if (prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true) && prefs.getBoolean("prefs_key_system_framework_core_patch_use_pre_signature", false)) { //If we decide to crack this then at least make sure they are same apks, avoid another one that tries to impersonate. if (param.getResult().equals(false)) { String pPname = (String) XposedHelpers.callMethod(param.args[1], "getPackageName"); if (pPname.contentEquals((String) param.args[0])) { param.setResult(true); } } } } }); var assertMinSignatureSchemeIsValid = XposedHelpers.findMethodExactIfExists("com.android.server.pm.ScanPackageUtils", loadPackageParam.classLoader, "assertMinSignatureSchemeIsValid", "com.android.server.pm.parsing.pkg.AndroidPackage", int.class); if (assertMinSignatureSchemeIsValid != null) { XposedBridge.hookMethod(assertMinSignatureSchemeIsValid, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) { if (prefs.getBoolean("prefs_key_system_framework_core_patch_auth_creak", true)) { param.setResult(null); } } }); } Class strictJarVerifier = findClass("android.util.jar.StrictJarVerifier", loadPackageParam.classLoader); if (strictJarVerifier != null) { XposedBridge.hookAllConstructors(strictJarVerifier, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) { if (prefs.getBoolean("prefs_key_system_framework_core_patch_auth_creak", true)) { XposedHelpers.setBooleanField(param.thisObject, "signatureSchemeRollbackProtectionsEnforced", false); } } }); } } @Override Class getSigningDetails(ClassLoader classLoader) { return XposedHelpers.findClassIfExists("android.content.pm.SigningDetails", classLoader); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/corepatch/CorePatchForU.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.corepatch; import static com.sevtinge.cemiuiler.module.app.SystemFrameworkForCorePatch.TAG; import android.util.Log; import java.lang.reflect.InvocationTargetException; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class CorePatchForU extends CorePatchForT { @Override public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws IllegalAccessException, InvocationTargetException, InstantiationException { super.handleLoadPackage(loadPackageParam); var utilClass = findClass("com.android.server.pm.ReconcilePackageUtils", loadPackageParam.classLoader); if (utilClass != null) { try { deoptimizeMethod(utilClass, "reconcilePackages"); } catch (Throwable e) { XposedBridge.log("[E" + TAG + " deoptimizing failed" + Log.getStackTraceString(e)); } } // ee11a9c (Rename AndroidPackageApi to AndroidPackage) findAndHookMethod("com.android.server.pm.PackageManagerServiceUtils", loadPackageParam.classLoader, "checkDowngrade", "com.android.server.pm.pkg.AndroidPackage", "android.content.pm.PackageInfoLite", new ReturnConstant(prefs, "prefs_key_system_framework_core_patch_downgr", null)); findAndHookMethod("com.android.server.pm.InstallPackageHelper", loadPackageParam.classLoader, "doesSignatureMatchForPermissions", String.class, "com.android.server.pm.parsing.pkg.ParsedPackage", int.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) { if (prefs.getBoolean("prefs_key_system_framework_core_patch_digest_creak", true) && prefs.getBoolean("prefs_key_system_framework_core_patch_use_pre_signature", false)) { //If we decide to crack this then at least make sure they are same apks, avoid another one that tries to impersonate. if (param.getResult().equals(false)) { String pPname = (String) XposedHelpers.callMethod(param.args[1], "getPackageName"); if (pPname.contentEquals((String) param.args[0])) { param.setResult(true); } } } } }); findAndHookMethod("com.android.server.pm.ScanPackageUtils", loadPackageParam.classLoader, "assertMinSignatureSchemeIsValid", "com.android.server.pm.pkg.AndroidPackage", int.class, new XC_MethodHook() { @Override protected void afterHookedMethod(MethodHookParam param) { if (prefs.getBoolean("prefs_key_system_framework_core_patch_auth_creak", true)) { param.setResult(null); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/corepatch/ReturnConstant.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.corepatch; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XSharedPreferences; public class ReturnConstant extends XC_MethodHook { private final XSharedPreferences prefs; private final String prefsKey; private final Object value; public ReturnConstant(XSharedPreferences prefs, String prefsKey, Object value) { this.prefs = prefs; this.prefsKey = prefsKey; this.value = value; } @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { super.beforeHookedMethod(param); prefs.reload(); if (prefs.getBoolean(prefsKey, true)) { param.setResult(value); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/corepatch/XposedHelper.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.corepatch; import static com.sevtinge.cemiuiler.module.app.SystemFrameworkForCorePatch.TAG; import android.util.Log; import com.sevtinge.cemiuiler.BuildConfig; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; public class XposedHelper { public final String SIGNATURE = "308203c6308202aea003020102021426d148b7c65944abcf3a683b4c3dd3b139c4ec85300d06092a864886f70d01010b05003074310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f69643110300e06035504031307416e64726f6964301e170d3139303130323138353233385a170d3439303130323138353233385a3074310b3009060355040613025553311330110603550408130a43616c69666f726e6961311630140603550407130d4d6f756e7461696e205669657731143012060355040a130b476f6f676c6520496e632e3110300e060355040b1307416e64726f69643110300e06035504031307416e64726f696430820122300d06092a864886f70d01010105000382010f003082010a028201010087fcde48d9beaeba37b733a397ae586fb42b6c3f4ce758dc3ef1327754a049b58f738664ece587994f1c6362f98c9be5fe82c72177260c390781f74a10a8a6f05a6b5ca0c7c5826e15526d8d7f0e74f2170064896b0cf32634a388e1a975ed6bab10744d9b371cba85069834bf098f1de0205cdee8e715759d302a64d248067a15b9beea11b61305e367ac71b1a898bf2eec7342109c9c5813a579d8a1b3e6a3fe290ea82e27fdba748a663f73cca5807cff1e4ad6f3ccca7c02945926a47279d1159599d4ecf01c9d0b62e385c6320a7a1e4ddc9833f237e814b34024b9ad108a5b00786ea15593a50ca7987cbbdc203c096eed5ff4bf8a63d27d33ecc963990203010001a350304e300c0603551d13040530030101ff301d0603551d0e04160414a361efb002034d596c3a60ad7b0332012a16aee3301f0603551d23041830168014a361efb002034d596c3a60ad7b0332012a16aee3300d06092a864886f70d01010b0500038201010022ccb684a7a8706f3ee7c81d6750fd662bf39f84805862040b625ddf378eeefae5a4f1f283deea61a3c7f8e7963fd745415153a531912b82b596e7409287ba26fb80cedba18f22ae3d987466e1fdd88e440402b2ea2819db5392cadee501350e81b8791675ea1a2ed7ef7696dff273f13fb742bb9625fa12ce9c2cb0b7b3d94b21792f1252b1d9e4f7012cb341b62ff556e6864b40927e942065d8f0f51273fcda979b8832dd5562c79acf719de6be5aee2a85f89265b071bf38339e2d31041bc501d5e0c034ab1cd9c64353b10ee70b49274093d13f733eb9d3543140814c72f8e003f301c7a00b1872cc008ad55e26df2e8f07441002c4bcb7dc746745f0db"; public static void findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback) { try { if (findClass(className, classLoader) != null) { XposedHelpers.findAndHookMethod(className, classLoader, methodName, parameterTypesAndCallback); } } catch (Throwable e) { if (BuildConfig.DEBUG) XposedBridge.log("[E" + TAG + ": " + Log.getStackTraceString(e)); } } public static void findAndHookMethod(Class clazz, String methodName, Object... parameterTypesAndCallback) { try { if (clazz != null) { XposedHelpers.findAndHookMethod(clazz, methodName, parameterTypesAndCallback); } } catch (Throwable e) { if (BuildConfig.DEBUG) XposedBridge.log("[E" + TAG + ": " + Log.getStackTraceString(e)); } } public static void hookAllMethods(String className, ClassLoader classLoader, String methodName, XC_MethodHook callback) { try { Class packageParser = findClass(className, classLoader); XposedBridge.hookAllMethods(packageParser, methodName, callback); } catch (Throwable e) { if (BuildConfig.DEBUG) XposedBridge.log("[E" + TAG + ": " + Log.getStackTraceString(e)); } } public void hookAllMethods(Class hookClass, String methodName, XC_MethodHook callback) { try { XposedBridge.hookAllMethods(hookClass, methodName, callback); } catch (Throwable e) { if (BuildConfig.DEBUG) XposedBridge.log("[E" + TAG + ": " + Log.getStackTraceString(e)); } } public static Class findClass(String className, ClassLoader classLoader) { try { return Class.forName(className, false, classLoader); } catch (Throwable e) { if (BuildConfig.DEBUG) XposedBridge.log("[E" + TAG + ": " + Log.getStackTraceString(e)); } return null; } public static void hookAllConstructors(String className, XC_MethodHook callback) { try { Class packageParser = findClass(className, null); XposedBridge.hookAllConstructors(packageParser, callback); } catch (Throwable e) { if (BuildConfig.DEBUG) XposedBridge.log("[E" + TAG + ": " + Log.getStackTraceString(e)); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/display/AutoBrightness.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.display; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.net.Uri; import android.os.Handler; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.MathUtils; import de.robv.android.xposed.XposedHelpers; public class AutoBrightness extends BaseHook { private static float mMaximumBacklight; private static float mMinimumBacklight; private static int backlightMaxLevel; private static float constrainValue(float val) { if (val < 0) val = 0; if (val > 1) val = 1; boolean limit_min = mPrefsMap.getBoolean("system_control_center_auto_brightness_min"); boolean limit_max = mPrefsMap.getBoolean("system_control_center_auto_brightness_max"); int min_pct = mPrefsMap.getInt("system_ui_auto_brightness_min", 25); int max_pct = mPrefsMap.getInt("system_ui_auto_brightness_max", 75); float min, max; min = MathUtils.convertGammaToLinearFloat(min_pct / 100f * backlightMaxLevel, backlightMaxLevel, mMinimumBacklight, mMaximumBacklight); max = MathUtils.convertGammaToLinearFloat(max_pct / 100f * backlightMaxLevel, backlightMaxLevel, mMinimumBacklight, mMaximumBacklight); if (limit_min && val < min) val = min; if (limit_max && val > max) val = max; return val; } @Override public void init() { Helpers.findAndHookMethod("com.android.server.display.AutomaticBrightnessController", lpparam.classLoader, "clampScreenBrightness", float.class, new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { float val = (float) param.getResult(); if (val >= 0) { float res = constrainValue(val); param.setResult(res); } } }); Helpers.hookAllConstructors("com.android.server.display.AutomaticBrightnessController", lpparam.classLoader, new Helpers.MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { XposedHelpers.setLongField(param.thisObject, "mBrighteningLightDebounceConfig", 1000L); XposedHelpers.setLongField(param.thisObject, "mDarkeningLightDebounceConfig", 1200L); } }); Helpers.findAndHookMethod("com.android.server.display.DisplayPowerController", lpparam.classLoader, "clampScreenBrightness", float.class, new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { float val = (float) param.getResult(); if (val >= 0) { float res = constrainValue(val); param.setResult(res); } } }); Helpers.hookAllConstructors("com.android.server.display.DisplayPowerController", lpparam.classLoader, new Helpers.MethodHook() { @Override @SuppressLint("DiscouragedApi") protected void before(final MethodHookParam param) throws Throwable { Resources res = Resources.getSystem(); int minBrightnessLevel = res.getInteger(res.getIdentifier("config_screenBrightnessSettingMinimum", "integer", "android")); int maxBrightnessLevel = res.getInteger(res.getIdentifier("config_screenBrightnessSettingMaximum", "integer", "android")); int backlightBit = res.getInteger(res.getIdentifier("config_backlightBit", "integer", "android.miui")); backlightMaxLevel = (1 << backlightBit) - 1; mMinimumBacklight = (minBrightnessLevel - 1) * 1.0f / (backlightMaxLevel - 1); mMaximumBacklight = (maxBrightnessLevel - 1) * 1.0f / (backlightMaxLevel - 1); } @Override protected void after(final MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); Handler mHandler = (Handler) XposedHelpers.getObjectField(param.thisObject, "mHandler"); new Helpers.SharedPrefObserver(mContext, mHandler) { @Override public void onChange(Uri uri) { try { String type = uri.getPathSegments().get(1); String key = uri.getPathSegments().get(2); switch (type) { case "integer" -> { int defVal = "pref_key_system_control_center_min_brightness".equals(key) ? 25 : 75; mPrefsMap.put(key, Helpers.getSharedIntPref(mContext, key, defVal)); } case "boolean" -> mPrefsMap.put(key, Helpers.getSharedBoolPref(mContext, key, false)); } } catch (Throwable t) { LogD(TAG, "onChange", t); } } }; } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/display/DisplayCutout.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.display import com.sevtinge.cemiuiler.module.base.BaseHook object DisplayCutout : BaseHook() { override fun init() { hookAllMethods("android.view.DisplayCutout", "pathAndDisplayCutoutFromSpec", object : MethodHook() { override fun before(param: MethodHookParam) { param.args[0] = "M 0,0 H 0 V 0 Z" param.args[1] = "" } } ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/display/ToastTime.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.display; import android.content.Context; import android.os.Handler; import android.os.Message; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import java.util.ArrayList; import de.robv.android.xposed.XposedHelpers; public class ToastTime extends BaseHook { @Override public void init() { Helpers.findAndHookMethod("com.android.server.notification.NotificationManagerService", lpparam.classLoader, "showNextToastLocked", new MethodHook() { @Override @SuppressWarnings("unchecked") protected void after(MethodHookParam param) { Context mContext = (Context)XposedHelpers.callMethod(param.thisObject, "getContext"); Handler mHandler = (Handler)XposedHelpers.getObjectField(param.thisObject, "mHandler"); ArrayList mToastQueue = (ArrayList)XposedHelpers.getObjectField(param.thisObject, "mToastQueue"); if (mContext == null || mHandler == null || mToastQueue == null || mToastQueue.size() == 0) return; int mod = (Helpers.getSharedIntPref(mContext, "system_ui_display_toast_times", 0) - 4) * 1000; for (Object record: mToastQueue) if (record != null && mHandler.hasMessages(2, record)) { mHandler.removeCallbacksAndMessages(record); int duration = XposedHelpers.getIntField(record, "duration"); int delay = Math.max(1000, (duration == 1 ? 3500 : 2000) + mod); mHandler.sendMessageDelayed(Message.obtain(mHandler, 2, record), delay); } } }); Helpers.findAndHookMethod("com.android.server.policy.PhoneWindowManager", lpparam.classLoader, "systemReady", new MethodHook() { @Override protected void after(MethodHookParam param) { Context mContext = (Context)XposedHelpers.getObjectField(param.thisObject, "mContext"); Handler mHandler = (Handler)XposedHelpers.getObjectField(param.thisObject, "mHandler"); new Helpers.SharedPrefObserver(mContext, mHandler, "system_ui_display_toast_times", 0) { @Override public void onChange(String name, int defValue) { mPrefsMap.put(name, Helpers.getSharedIntPref(mContext, name, defValue)); } }; } }); String windowClass = "com.android.server.wm.DisplayPolicy"; Helpers.hookAllMethods(windowClass, lpparam.classLoader, "adjustWindowParamsLw", new MethodHook() { @Override protected void before(MethodHookParam param) { Object lp = param.args.length == 1 ? param.args[0] : param.args[1]; XposedHelpers.setAdditionalInstanceField(param.thisObject, "mPrevHideTimeout", XposedHelpers.getLongField(lp, "hideTimeoutMilliseconds")); } @Override protected void after(MethodHookParam param) { Object lp = param.args.length == 1 ? param.args[0] : param.args[1]; long mPrevHideTimeout = (long)XposedHelpers.getAdditionalInstanceField(param.thisObject, "mPrevHideTimeout"); long mHideTimeout = XposedHelpers.getLongField(lp, "hideTimeoutMilliseconds"); if (mPrevHideTimeout == -1 || mHideTimeout == -1) return; long dur = 0; if (mPrevHideTimeout == 1000 || mPrevHideTimeout == 4000 || mPrevHideTimeout == 5000 || mPrevHideTimeout == 7000 || mPrevHideTimeout != mHideTimeout) dur = Math.max(1000, 3500 + (mPrefsMap.getInt("system_ui_display_toast_times", 0) - 4) * 1000); if (dur != 0) XposedHelpers.setLongField(lp, "hideTimeoutMilliseconds", dur); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/freeform/OpenAppInFreeForm.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.freeform; import android.app.ActivityOptions; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.util.MiuiMultiWindowUtils; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.ArrayList; import java.util.List; import de.robv.android.xposed.XposedHelpers; import miui.app.MiuiFreeFormManager; public class OpenAppInFreeForm extends BaseHook { Class mActivityStarter; Class mActivityTaskManagerService; @Override public void init() { if (mPrefsMap.getBoolean("system_framework_freeform_jump")) { mActivityStarter = findClassIfExists("com.android.server.wm.ActivityStarter"); mActivityTaskManagerService = findClassIfExists("com.android.server.wm.ActivityTaskManagerService"); findAndHookMethod(mActivityTaskManagerService, "onSystemReady", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_PREFIX + "SetFreeFormPackage"); BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action == null) return; if (action.equals(ACTION_PREFIX + "SetFreeFormPackage")) { String pkg = intent.getStringExtra("package"); XposedHelpers.setAdditionalStaticField(MiuiFreeFormManager.class, "nextFreeformPackage", pkg); } } }; mContext.registerReceiver(mReceiver, intentFilter); } }); hookAllMethods(mActivityStarter, "executeRequest", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Object request = param.args[0]; Intent intent = (Intent) XposedHelpers.getObjectField(request, "intent"); Object safeOptions = XposedHelpers.getObjectField(request, "activityOptions"); if (safeOptions != null) { ActivityOptions ao = (ActivityOptions) XposedHelpers.getObjectField(safeOptions, "mOriginalOptions"); if (ao != null && XposedHelpers.getIntField(ao, "mLaunchWindowingMode") == 5) { return; } } String callingPackage = (String) XposedHelpers.getObjectField(request, "callingPackage"); boolean openInFw = shouldOpenInFreeForm(intent, callingPackage); // Bundle ao = safeOptions != null ? (Bundle) XposedHelpers.callMethod(safeOptions, "getActivityOptionsBundle") : null; // String reason = (String) XposedHelpers.getObjectField(request, "reason"); // Helpers.log("startAct: " + callingPackage // + " reason| " + reason // + " intent| " + intent // + " openInFw| " + openInFw // + " activityOptions| " + Helpers.stringifyBundle(ao) // + " intentExtra| " + Helpers.stringifyBundle(intent.getExtras()) // ); if (openInFw) { Context mContext = (Context) XposedHelpers.getObjectField(XposedHelpers.getObjectField(param.thisObject, "mService"), "mContext"); ActivityOptions options = MiuiMultiWindowUtils.getActivityOptions(mContext, intent.getComponent().getPackageName(), true, false); XposedHelpers.callMethod(param.thisObject, "setActivityOptions", options.toBundle()); } } }); } } private boolean shouldOpenInFreeForm(Intent intent, String callingPackage) { if (intent == null || intent.getComponent() == null) { return false; } final List fwBlackList = new ArrayList<>(); fwBlackList.add("com.miui.home"); fwBlackList.add("com.android.camera"); fwBlackList.add("com.android.systemui"); String pkgName = intent.getComponent().getPackageName(); if (fwBlackList.contains(pkgName)) { return false; } boolean openInFw = false; final boolean openFwWhenShare = mPrefsMap.getBoolean("system_framework_freeform_app_share"); if (openFwWhenShare) { /*if (mPrefsMap.getStringSet("system_fw_forcein_actionsend_apps").contains(pkgName)) return false;*/ if ("com.miui.packageinstaller".equals(pkgName) && intent.getComponent().getClassName().contains("com.miui.packageInstaller.NewPackageInstallerActivity")) { return true; } if (Intent.ACTION_SEND.equals(intent.getAction()) && !pkgName.equals(callingPackage)) { openInFw = true; } else if ("com.tencent.mm".equals(pkgName) && intent.getComponent().getClassName().contains(".plugin.base.stub.WXEntryActivity")) { openInFw = true; } } if (!openInFw) { Object pkg = XposedHelpers.getAdditionalStaticField(MiuiFreeFormManager.class, "nextFreeformPackage"); openInFw = pkgName.equals(pkg); if (openInFw) { XposedHelpers.removeAdditionalStaticField(MiuiFreeFormManager.class, "nextFreeformPackage"); } } return openInFw; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/mipad/IgnoreStylusKeyGesture.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.mipad import com.github.kyuubiran.ezxhelper.ClassUtils.loadFirstClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object IgnoreStylusKeyGesture : BaseHook() { override fun init() { val clazzMiuiStylusPageKeyListener = loadFirstClass( "com.miui.server.input.stylus.MiuiStylusPageKeyListener", "com.miui.server.stylus.MiuiStylusPageKeyListener" ) val methodNames = setOf("isPageKeyEnable", "needInterceptBeforeDispatching", "shouldInterceptKey") clazzMiuiStylusPageKeyListener.methodFinder().filter { name in methodNames }.toList().createHooks { returnConstant(false) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/mipad/NoMagicPointer.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.mipad import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.ClassUtils.loadClassOrNull import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object NoMagicPointer : BaseHook() { override fun init() { loadClassOrNull("android.magicpointer.util.MiuiMagicPointerUtils")?.methodFinder()?.first { name == "isEnable" }?.createHook { returnConstant(false) } loadClass("com.android.server.SystemServerImpl").methodFinder().first { name == "addMagicPointerManagerService" }.createHook { returnConstant(null) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/mipad/RemoveStylusBluetoothRestriction.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.mipad import com.github.kyuubiran.ezxhelper.ClassUtils.invokeStaticMethodBestMatch import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.ObjectUtils import com.sevtinge.cemiuiler.module.base.BaseHook object RemoveStylusBluetoothRestriction : BaseHook() { override fun init() { val clazzMiuiStylusDeviceListener = loadClass("com.miui.server.input.stylus.MiuiStylusDeviceListener") clazzMiuiStylusDeviceListener.declaredConstructors.createHooks { after { setTouchModeStylusEnable() } } clazzMiuiStylusDeviceListener.declaredMethods.createHooks { replace { setTouchModeStylusEnable() } } } private fun setTouchModeStylusEnable() { val driverVersion = mPrefsMap.getStringAsInt("mipad_input_bluetooth_version", 2) val flag: Int = 0x10 or driverVersion val instanceITouchFeature = invokeStaticMethodBestMatch( loadClass("miui.util.ITouchFeature"), "getInstance" )!! ObjectUtils.invokeMethodBestMatch( instanceITouchFeature, "setTouchMode", null, 0, 20, flag ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/mipad/RestoreEsc.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.mipad import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object RestoreEsc : BaseHook() { override fun init() { loadClass("com.android.server.input.config.InputCommonConfig").methodFinder().first { name == "setPadMode" }.createHook { before { it.args[0] = false } } loadClass("com.android.server.input.InputManagerServiceStubImpl").methodFinder().first { name == "switchPadMode" }.createHook { before { it.args[0] = false } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/mipad/SetGestureNeedFingerNum.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.mipad import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object SetGestureNeedFingerNum : BaseHook() { override fun init() { loadClass("com.miui.server.input.gesture.multifingergesture.gesture.BaseMiuiMultiFingerGesture").methodFinder() .first { name == "getFunctionNeedFingerNum" }.createHook { returnConstant(4) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/network/DualNRSupport.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.network import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object DualNRSupport : BaseHook() { override fun init() { runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isDualNrSupported" }.createHook { before { it.result = true } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/network/DualSASupport.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.network import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object DualSASupport : BaseHook() { override fun init() { runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isDualSaSupported" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/network/N1Band.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.network import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object N1Band : BaseHook() { override fun init() { runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isN1Supported" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/network/N28Band.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.network import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object N28Band : BaseHook() { override fun init() { runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isN28Supported" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemframework/network/N5N8Band.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemframework.network import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object N5N8Band : BaseHook() { override fun init() { runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isN5Supported" }.createHook { returnConstant(true) } } runCatching { loadClass("miui.telephony.TelephonyManagerEx").methodFinder().first { name == "isN8Supported" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/AddMiuiPlusEntry.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook; public class AddMiuiPlusEntry extends BaseHook { @Override public void init() { findAndHookMethod("com.android.settings.connection.MiMirrorController", "isMirrorSupported", new BaseHook.MethodHook() { @Override protected void before(XC_MethodHook.MethodHookParam param) { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/AppsFreezerEnable.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; public class AppsFreezerEnable extends BaseHook { @Override public void init() { Helpers.findAndHookMethod("com.android.settings.development.CachedAppsFreezerPreferenceController", lpparam.classLoader, "isAvailable", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); param.setResult(true); } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/EnableFoldArea.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings import com.github.kyuubiran.ezxhelper.ClassUtils.setStaticObject import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.LazyClass.SettingsFeaturesClass class EnableFoldArea : BaseHook() { override fun init() { setStaticObject( SettingsFeaturesClass, "IS_SUPPORT_FOLD_SCREEN_SETTINGS", true ) SettingsFeaturesClass.methodFinder().first(){ name == "isSupportFoldScreenSettings" }.createHook { before{ it.result = true } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/EnablePadArea.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings import com.github.kyuubiran.ezxhelper.ClassUtils.setStaticObject import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.LazyClass.SettingsFeaturesClass class EnablePadArea : BaseHook() { override fun init() { setStaticObject( SettingsFeaturesClass, "IS_SUPPORT_TABLET_SCREEN_SETTINGS", true ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/EnableSpeedMode.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings; import com.sevtinge.cemiuiler.module.base.BaseHook; public class EnableSpeedMode extends BaseHook { @Override public void init() { findAndHookMethod("com.android.settings.development.SpeedModeToolsPreferenceController", "getAvailabilityStatus", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(0); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/InternationalBuild.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; import miui.os.Build; public class InternationalBuild extends BaseHook { @Override public void init() { XposedHelpers.setStaticBooleanField(Build.class, "IS_INTERNATIONAL_BUILD", true); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/NewNFCPage.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings; import com.sevtinge.cemiuiler.module.base.BaseHook; public class NewNFCPage extends BaseHook { @Override public void init() { findAndHookMethod("com.android.settings.utils.SettingsFeatures", "isNeedShowMiuiNFC", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/NoveltyHaptic.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object NoveltyHaptic : BaseHook() { override fun init() { if (mPrefsMap.getBoolean("system_settings_international_build")) return // 开启国际版设置界面将禁用此功能 loadClass("com.android.settings.utils.SettingsFeatures").methodFinder().first { name == "isNoveltyHaptic" }.createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/QuickManageOverlayPermission.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings import android.app.Activity import android.os.Bundle import android.provider.Settings import com.github.kyuubiran.ezxhelper.ObjectHelper.Companion.objectHelper import com.sevtinge.cemiuiler.module.base.BaseHook class QuickManageOverlayPermission : BaseHook() { override fun init() { findAndHookMethod("com.android.settings.SettingsActivity", "redirectTabletActivity", Bundle::class.java, object : MethodHook() { override fun before(param: MethodHookParam) { val intent = (param.thisObject as Activity).intent if (intent.action != Settings.ACTION_MANAGE_OVERLAY_PERMISSION || intent.data == null || intent.data!!.scheme != "package") return@before param.thisObject.objectHelper().setObjectUntilSuperclass( "initialFragmentName", "com.android.settings.applications.appinfo.DrawOverlayDetails" ) } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/QuickManageUnknownAppSources.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings import android.app.Activity import android.os.Bundle import android.provider.Settings import com.github.kyuubiran.ezxhelper.ObjectHelper.Companion.objectHelper import com.sevtinge.cemiuiler.module.base.BaseHook class QuickManageUnknownAppSources : BaseHook() { override fun init() { findAndHookMethod("com.android.settings.SettingsActivity", "redirectTabletActivity", Bundle::class.java, object : MethodHook() { override fun before(param: MethodHookParam) { val intent = (param.thisObject as Activity).intent if (intent.action != Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES || intent.data == null || intent.data!!.scheme != "package") return@before param.thisObject.objectHelper().setObjectUntilSuperclass( "initialFragmentName", "com.android.settings.applications.appinfo.ExternalSourcesDetails" ) } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/UnLockAreaScreenshot.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings import com.sevtinge.cemiuiler.module.base.BaseHook object UnLockAreaScreenshot : BaseHook() { override fun init() { findAndHookMethod( "com.android.settings.MiuiShortcut\$System", "supportPartialScreenShot", object : MethodHook() { override fun before(param: MethodHookParam?) { param?.result = true } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/UnlockTaplusForSettings.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object UnlockTaplusForSettings : BaseHook() { override fun init() { loadClass("com.android.settings.utils.SettingsFeatures").methodFinder().first { name == "isNeedRemoveContentExtension" }.createHook { returnConstant(false) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/ViewWifiPasswordHook.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; public class ViewWifiPasswordHook extends BaseHook { @Override public void init() { int titleId = mResHook.addResource("system_wifipassword_btn_title", R.string.system_settings_wifipassword_btn_title); int dlgTitleId = mResHook.addResource("system_wifi_password_dlgtitle", R.string.system_settings_wifi_password_dlgtitle); Helpers.hookAllMethods("com.android.settings.wifi.SavedAccessPointPreference", lpparam.classLoader, "onBindViewHolder", new MethodHook() { @Override @SuppressLint("DiscouragedApi") protected void after(MethodHookParam param) throws Throwable { View view = (View) XposedHelpers.getObjectField(param.thisObject, "mView"); int btnId = view.getResources().getIdentifier("btn_delete", "id", "com.android.settings"); Button button = view.findViewById(btnId); button.setText(titleId); } }); final String[] wifiSharedKey = new String[1]; final String[] passwordTitle = new String[1]; Helpers.findAndHookMethod("miuix.appcompat.app.AlertDialog$Builder", lpparam.classLoader, "setTitle", int.class, new MethodHook() { @Override protected void before(MethodHookParam param) { if (wifiSharedKey[0] != null) { param.args[0] = dlgTitleId; } } }); Helpers.findAndHookMethod("miuix.appcompat.app.AlertDialog$Builder", lpparam.classLoader, "setMessage", CharSequence.class, new MethodHook() { @Override protected void before(MethodHookParam param) { if (wifiSharedKey[0] != null) { CharSequence str = (CharSequence) param.args[0]; str = str + "\n" + passwordTitle[0] + ": " + wifiSharedKey[0]; param.args[0] = str; } } }); Helpers.hookAllMethods("miuix.appcompat.app.AlertDialog", lpparam.classLoader, "onCreate", new MethodHook() { @Override protected void after(MethodHookParam param) { if (wifiSharedKey[0] != null) { TextView messageView = (TextView) XposedHelpers.callMethod(param.thisObject, "getMessageView"); messageView.setTextIsSelectable(true); } } }); Helpers.hookAllMethods("com.android.settings.wifi.MiuiSavedAccessPointsWifiSettings", lpparam.classLoader, "showDeleteDialog", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Object wifiEntry = param.args[0]; boolean canShare = (boolean) XposedHelpers.callMethod(wifiEntry, "canShare"); if (canShare) { if (passwordTitle[0] == null) { Resources modRes = Helpers.getModuleRes((Context) XposedHelpers.callMethod(param.thisObject, "getContext")); passwordTitle[0] = modRes.getString(R.string.system_settings_wifi_password_label); } String sharedKey = getSharedKey(param, wifiEntry); wifiSharedKey[0] = sharedKey; } } @Override protected void after(MethodHookParam param) { Object wifiEntry = param.args[0]; boolean canShare = (boolean) XposedHelpers.callMethod(wifiEntry, "canShare"); if (canShare) { wifiSharedKey[0] = null; } } }); } private String getSharedKey(XC_MethodHook.MethodHookParam param, Object wifiEntry) { Object mWifiManager = XposedHelpers.getObjectField(param.thisObject, "mWifiManager"); Object wifiConfiguration = XposedHelpers.callMethod(wifiEntry, "getWifiConfiguration"); Class WifiDppUtilsClass = XposedHelpers.findClass("com.android.settings.wifi.dpp.WifiDppUtils", lpparam.classLoader); String sharedKey = (String) XposedHelpers.callStaticMethod(WifiDppUtilsClass, "getPresharedKey", mWifiManager, wifiConfiguration); sharedKey = (String) XposedHelpers.callStaticMethod(WifiDppUtilsClass, "removeFirstAndLastDoubleQuotes", sharedKey); return sharedKey; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/VoipAssistantController.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings; import com.sevtinge.cemiuiler.module.base.BaseHook; public class VoipAssistantController extends BaseHook { @Override public void init() { findAndHookMethod("com.android.settings.lab.MiuiVoipAssistantController", "isNotSupported", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(false); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/aiimage/UnlockAi.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings.aiimage; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockAi extends BaseHook { @Override public void init() { findAndHookMethod("com.android.settings.display.ScreenEnhanceEngineStatusCheck", "isAiSupport", Context.class, new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/aiimage/UnlockMemc.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings.aiimage; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockMemc extends BaseHook { @Override public void init() { findAndHookMethod("com.android.settings.display.ScreenEnhanceEngineStatusCheck", "isMemcSupport", new BaseHook.MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemsettings/aiimage/UnlockSuperResolution.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemsettings.aiimage; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; public class UnlockSuperResolution extends BaseHook { @Override public void init() { findAndHookMethod("com.android.settings.display.ScreenEnhanceEngineStatusCheck", "getSrForVideoStatus", Context.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true); } }); findAndHookMethod("com.android.settings.display.ScreenEnhanceEngineStatusCheck", "getSrForImageStatus", Context.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true); } }); findAndHookMethod("com.android.settings.display.ScreenEnhanceEngineStatusCheck", "getS2hStatus", Context.class, new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true); } }); findAndHookMethod("com.android.settings.display.ScreenEnhanceEngineStatusCheck", "isSrForVideoSupport", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true); } }); findAndHookMethod("com.android.settings.display.ScreenEnhanceEngineStatusCheck", "isSrForImageSupport", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true); } }); findAndHookMethod("com.android.settings.display.ScreenEnhanceEngineStatusCheck", "isS2hSupport", new MethodHook() { @Override protected void before(MethodHookParam param) { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/AutoCollapse.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import de.robv.android.xposed.XposedHelpers; public class AutoCollapse extends BaseHook { @Override public void init() { Helpers.findAndHookMethod("com.android.systemui.qs.tileimpl.QSTileImpl", lpparam.classLoader, "click", View.class, new MethodHook() { @Override protected void after(MethodHookParam param) { Object mState = XposedHelpers.callMethod(param.thisObject, "getState"); int state = XposedHelpers.getIntField(mState, "state"); if (state != 0) { String tileSpec = (String) XposedHelpers.callMethod(param.thisObject, "getTileSpec"); if (!"edit".equals(tileSpec)) { Object mHost = XposedHelpers.getObjectField(param.thisObject, "mHost"); XposedHelpers.callMethod(mHost, "collapsePanels"); } } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/BatteryIndicator.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Rect; import android.view.View; import android.widget.FrameLayout; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.view.BatteryIndicatorView; import de.robv.android.xposed.XposedHelpers; public class BatteryIndicator extends BaseHook { @Override @SuppressLint("DiscouragedApi") public void init() { hookAllMethods("com.android.systemui.statusbar.phone.StatusBar", "makeStatusBarView", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); FrameLayout mStatusBarWindow = (FrameLayout) XposedHelpers.getObjectField(param.thisObject, "mPhoneStatusBarWindow"); BatteryIndicatorView indicator = new BatteryIndicatorView(mContext); View panel = mStatusBarWindow.findViewById(mContext.getResources().getIdentifier("notification_panel", "id", lpparam.packageName)); mStatusBarWindow.addView(indicator, panel != null ? mStatusBarWindow.indexOfChild(panel) + 1 : Math.max(mStatusBarWindow.getChildCount() - 1, 2)); indicator.setAdjustViewBounds(false); indicator.init(param.thisObject); XposedHelpers.setAdditionalInstanceField(param.thisObject, "mBatteryIndicator", indicator); Object mNotificationIconAreaController = XposedHelpers.getObjectField(param.thisObject, "mNotificationIconAreaController"); XposedHelpers.setAdditionalInstanceField(mNotificationIconAreaController, "mBatteryIndicator", indicator); Object mBatteryController = XposedHelpers.getObjectField(param.thisObject, "mBatteryController"); XposedHelpers.setAdditionalInstanceField(mBatteryController, "mBatteryIndicator", indicator); XposedHelpers.callMethod(mBatteryController, "fireBatteryLevelChanged"); XposedHelpers.callMethod(mBatteryController, "firePowerSaveChanged"); // XposedHelpers.callMethod(mBatteryController, "fireExtremePowerSaveChanged"); } }); findAndHookMethod("com.android.systemui.statusbar.phone.StatusBar", "setPanelExpanded", boolean.class, new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { boolean isKeyguardShowing = (boolean) XposedHelpers.callMethod(param.thisObject, "isKeyguardShowing"); BatteryIndicatorView indicator = (BatteryIndicatorView) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mBatteryIndicator"); if (indicator != null) indicator.onExpandingChanged(!isKeyguardShowing && (boolean) param.args[0]); } }); findAndHookMethod("com.android.systemui.statusbar.phone.StatusBar", "setQsExpanded", boolean.class, new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { boolean isKeyguardShowing = (boolean) XposedHelpers.callMethod(param.thisObject, "isKeyguardShowing"); if (!isKeyguardShowing) return; BatteryIndicatorView indicator = (BatteryIndicatorView) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mBatteryIndicator"); if (indicator != null) indicator.onExpandingChanged((boolean) param.args[0]); } }); findAndHookMethod("com.android.systemui.statusbar.phone.StatusBar", "updateKeyguardState", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { boolean isKeyguardShowing = (boolean) XposedHelpers.callMethod(param.thisObject, "isKeyguardShowing"); BatteryIndicatorView indicator = (BatteryIndicatorView) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mBatteryIndicator"); if (indicator != null) indicator.onKeyguardStateChanged(isKeyguardShowing); } }); findAndHookMethod("com.android.systemui.statusbar.phone.NotificationIconAreaController", "onDarkChanged", Rect.class, float.class, int.class, new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { BatteryIndicatorView indicator = (BatteryIndicatorView) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mBatteryIndicator"); if (indicator != null) indicator.onDarkModeChanged((float) param.args[1], (int) param.args[2]); } }); findAndHookMethod("com.android.systemui.statusbar.policy.MiuiBatteryControllerImpl", "fireBatteryLevelChanged", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { BatteryIndicatorView indicator = (BatteryIndicatorView) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mBatteryIndicator"); int mLevel = XposedHelpers.getIntField(param.thisObject, "mLevel"); boolean mCharging = XposedHelpers.getBooleanField(param.thisObject, "mCharging"); boolean mCharged = XposedHelpers.getBooleanField(param.thisObject, "mCharged"); if (indicator != null) indicator.onBatteryLevelChanged(mLevel, mCharging, mCharged); } }); findAndHookMethod("com.android.systemui.statusbar.policy.BatteryControllerImpl", "firePowerSaveChanged", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { BatteryIndicatorView indicator = (BatteryIndicatorView) XposedHelpers.getAdditionalInstanceField(param.thisObject, "mBatteryIndicator"); if (indicator != null) indicator.onPowerSaveChanged(XposedHelpers.getBooleanField(param.thisObject, "mPowerSave")); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/BluetoothRestrict.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.content.Context; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; public class BluetoothRestrict extends BaseHook { Class mLocalBluetoothAdapter; @Override public void init() { mLocalBluetoothAdapter = findClassIfExists("com.android.settingslib.bluetooth.LocalBluetoothAdapter"); findAndHookMethod(mLocalBluetoothAdapter, "isSupportBluetoothRestrict", Context.class, XC_MethodReplacement.returnConstant(false)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/ChargeAnimationStyle.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.util.ArraySet; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.util.Set; import de.robv.android.xposed.XposedHelpers; public class ChargeAnimationStyle extends BaseHook { Class mChargeAnimCls; Class mWaveViewCls; int mChargeAnimationType; int mType; @Override public void init() { mChargeAnimCls = findClassIfExists("com.android.keyguard.charge.ChargeUtils"); mWaveViewCls = findClassIfExists("com.android.keyguard.charge.wave.WaveView"); mChargeAnimationType = mPrefsMap.getStringAsInt("system_ui_charge_animation_style", 0); setChargeAnimationType(mChargeAnimationType); } public void setChargeAnimationType(int value) { if (value == 1) { findAndHookMethod(mChargeAnimCls, "isChargeAnimationDisabled", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { param.setResult(true); } }); } else if (value == 4) { findAndHookMethod(mChargeAnimCls, "supportWaveChargeAnimation", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { StackTraceElement[] stackElement = new Throwable().getStackTrace(); boolean mResult = false; Set classTrue = new ArraySet<>(new String[]{"com.android.keyguard.charge.ChargeUtils", "com.android.keyguard.charge.container.MiuiChargeContainerView"}); int i = 0; int length = stackElement.length; while (true) { if (i >= length) { break; } else if (!classTrue.contains(stackElement[i].getClassName())) { i++; } else { mResult = true; XposedLogUtils.logI(TAG, stackElement[i].getClassName()); break; } } param.setResult(mResult); } }); findAndHookMethod(mWaveViewCls, "updateWaveHeight", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.setIntField(param.thisObject, "mWaveXOffset", 0); } }); /*findAndHookMethod(mChargeAnimCls,"getChargeAnimationType", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(2); } }); findAndHookMethod(mWaveViewCls, "updateWaveHeight" ,new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.setIntField(param.thisObject, "mWaveXOffset", 0); } });*/ } else { switch (value) { case 2 -> mType = 0; case 3 -> mType = 1; } findAndHookMethod(mChargeAnimCls, "getChargeAnimationType", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(mType); } }); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/ClockCenterHook.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.content.Context; import android.content.res.Resources; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import de.robv.android.xposed.XposedHelpers; public class ClockCenterHook extends BaseHook { private static LinearLayout mLeftLayout = null; private static LinearLayout mRightLayout = null; private static LinearLayout mCenterLayout; private static ViewGroup statusBar = null; Class mStatusBarView; @Override public void init() { mStatusBarView = findClassIfExists("com.android.systemui.statusbar.phone.CollapsedStatusBarFragment"); Helpers.findAndHookMethod(mStatusBarView, "onViewCreated", View.class, Bundle.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ViewGroup miuiPhoneStatusBarView = (ViewGroup) XposedHelpers.getObjectField(param.thisObject, "mStatusBar"); Context context = miuiPhoneStatusBarView.getContext(); Resources res = miuiPhoneStatusBarView.getResources(); int statusBarId = res.getIdentifier("status_bar", "id", "com.android.systemui"); int statusBarContentsId = res.getIdentifier("status_bar_contents", "id", "com.android.systemui"); int systemIconAreaId = res.getIdentifier("system_icon_area", "id", "com.android.systemui"); int clockId = res.getIdentifier("clock", "id", "com.android.systemui"); int phoneStatusBarLeftContainerId = res.getIdentifier( "phone_status_bar_left_container", "id", "com.android.systemui" ); int fullscreenNotificationIconAreaId = res.getIdentifier( "fullscreen_notification_icon_area", "id", "com.android.systemui" ); int statusIconsId = res.getIdentifier( "statusIcons", "id", "com.android.systemui" ); int systemIconsId = res.getIdentifier( "system_icons", "id", "com.android.systemui" ); int batteryId = res.getIdentifier( "battery", "id", "com.android.systemui" ); statusBar = miuiPhoneStatusBarView.findViewById(statusBarId); ViewGroup statusBarContents = miuiPhoneStatusBarView.findViewById(statusBarContentsId); TextView clock = miuiPhoneStatusBarView.findViewById(clockId); ViewGroup phoneStatusBarLeftContainer = miuiPhoneStatusBarView.findViewById(phoneStatusBarLeftContainerId); ViewGroup fullscreenNotificationIconArea = miuiPhoneStatusBarView.findViewById(fullscreenNotificationIconAreaId); ViewGroup systemIconArea = miuiPhoneStatusBarView.findViewById(systemIconAreaId); ViewGroup statusIcons = miuiPhoneStatusBarView.findViewById(statusIconsId); ViewGroup systemIcons = miuiPhoneStatusBarView.findViewById(systemIconsId); ViewGroup battery = miuiPhoneStatusBarView.findViewById(batteryId); ((ViewGroup) clock.getParent()).removeView(clock); ((ViewGroup) phoneStatusBarLeftContainer).removeView(phoneStatusBarLeftContainer); ((ViewGroup) systemIconArea.getParent()).removeView(systemIconArea); ((ViewGroup) statusIcons.getParent()).removeView(statusIcons); ((ViewGroup) systemIcons.getParent()).removeView(systemIcons); ((ViewGroup) battery.getParent()).removeView(battery); ((ViewGroup) fullscreenNotificationIconArea.getParent()).removeView( fullscreenNotificationIconArea ); FrameLayout mConstraintLayout = new FrameLayout(context); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); mConstraintLayout.setLayoutParams(layoutParams); mConstraintLayout.addView(fullscreenNotificationIconArea); mConstraintLayout.addView(battery); FrameLayout.LayoutParams layoutParams2 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.MATCH_PARENT); battery.setLayoutParams(layoutParams2); FrameLayout.LayoutParams layoutParams3 = new FrameLayout.LayoutParams(0, FrameLayout.LayoutParams.MATCH_PARENT); fullscreenNotificationIconArea.setLayoutParams(layoutParams3); fullscreenNotificationIconArea.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); // 增加一个左对齐布局 mLeftLayout = new LinearLayout(context); LinearLayout.LayoutParams leftLp = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f); mLeftLayout.setLayoutParams(leftLp); mLeftLayout.setGravity(Gravity.START | Gravity.CENTER_VERTICAL); // 增加一个居中布局 mCenterLayout = new LinearLayout(context); LinearLayout.LayoutParams centerLp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT ); mCenterLayout.setLayoutParams(centerLp); mCenterLayout.setGravity(Gravity.CENTER | Gravity.CENTER_VERTICAL); // 增加一个右布局 mRightLayout = new LinearLayout(context); LinearLayout.LayoutParams rightLp = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f); mRightLayout.setLayoutParams(rightLp); mRightLayout.setGravity(Gravity.END | Gravity.CENTER_VERTICAL); mLeftLayout.addView(phoneStatusBarLeftContainer); mLeftLayout.addView(statusIcons); statusIcons.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); mCenterLayout.addView(clock); mRightLayout.addView(mConstraintLayout); fullscreenNotificationIconArea.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); statusBarContents.addView(mLeftLayout, 0); statusBarContents.addView(mCenterLayout); statusBarContents.addView(mRightLayout); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/EnableVolumeBlur.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.HookUtils import com.sevtinge.cemiuiler.utils.log.XposedLogUtils.logW import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers class EnableVolumeBlur : BaseHook() { override fun init() { hookClassInPlugin { classLoader -> try { val volumeUtilClass = XposedHelpers.callMethod( classLoader, "loadClass", "com.android.systemui.miui.volume.Util" ) ?: return@hookClassInPlugin volumeUtilClass as Class<*> val allVolumeUtilMethods = volumeUtilClass.methods if (allVolumeUtilMethods.isEmpty()) { return@hookClassInPlugin } allVolumeUtilMethods.forEach { method -> if (method.name == "isSupportBlurS") { XposedBridge.hookAllMethods( volumeUtilClass, "isSupportBlurS", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { try { if (param.result is Boolean) { param.result = true } } catch (e: Throwable) { // Do Nothings. logW(TAG, e) } } }) return@hookClassInPlugin } } } catch (e: Throwable) { // Do Nothings. logW(TAG, e) } } } private fun hookClassInPlugin(afterGetClassLoader: (classLoader: ClassLoader) -> Unit) { val pluginHandlerClass = findClassIfExists( "com.android.systemui.shared.plugins.PluginInstanceManager\$PluginHandler" ) if (pluginHandlerClass != null) { XposedBridge.hookAllMethods(pluginHandlerClass, "handleLoadPlugin", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val componentName = param.args[0] val className = XposedHelpers.callMethod(componentName, "getClassName") as String if (className != "miui.systemui.volume.VolumeDialogPlugin") { return } try { val pluginContextWrapper = HookUtils.getValueByField(param.result ?: return, "mPluginContext") ?: return val classLoader = XposedHelpers.callMethod( pluginContextWrapper, "getClassLoader" ) as ClassLoader afterGetClassLoader(classLoader) } catch (e: Throwable) { // Do Nothings. logW("$TAG => hookClassInPlugin", e) } } }) return } val pluginActionManagerClass = findClassIfExists( "com.android.systemui.shared.plugins.PluginActionManager" ) if (pluginActionManagerClass != null) { XposedBridge.hookAllMethods(pluginActionManagerClass, "loadPluginComponent", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val componentName = param.args[0] val className = XposedHelpers.callMethod(componentName, "getClassName") as String if (className != "miui.systemui.volume.VolumeDialogPlugin") { return } try { val pluginContextWrapper = HookUtils.getValueByField(param.result ?: return, "mPluginContext") ?: return val classLoader = XposedHelpers.callMethod( pluginContextWrapper, "getClassLoader" ) as ClassLoader afterGetClassLoader(classLoader) } catch (e: Throwable) { // Do Nothings. logW(TAG, e) } } }) return } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/HideNavigationBar.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidU; import android.annotation.SuppressLint; import android.content.Context; import android.database.ContentObserver; import android.os.Handler; import android.provider.Settings; import android.widget.Toast; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.util.Locale; import de.robv.android.xposed.XposedHelpers; public class HideNavigationBar extends BaseHook { boolean run = false; @Override public void init() { /*启用隐藏*/ if (isAndroidU()) { hookAllConstructors("com.android.systemui.statusbar.phone.NavigationModeControllerExt", new MethodHook() { @SuppressLint("PrivateApi") @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); XposedHelpers.setStaticBooleanField(param.getClass().getClassLoader().loadClass("com.android.systemui.statusbar.phone.NavigationModeControllerExt"), "mHideGestureLine", true); } }); } else { findAndHookMethod("com.android.systemui.statusbar.phone.NavigationModeControllerExt", "hideNavigationBar", new MethodHook() { @Override protected void after(MethodHookParam param) { param.setResult(true); } } ); } /*不隐藏时创建手势条*/ hookAllMethods("com.android.systemui.navigationbar.NavigationBarController", "createNavigationBar", new MethodHook() { @Override protected void before(MethodHookParam param) { if (param.args.length >= 3) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); ContentObserver(mContext); try { int End = Settings.Global.getInt(mContext.getContentResolver(), "hide_gesture_line"); if (End == 1) { Settings.Global.putInt(mContext.getContentResolver(), "hide_gesture_line", 0); XposedLogUtils.logI("Settings The hide_gesture_line To 0"); } } catch (Settings.SettingNotFoundException e) { XposedLogUtils.logI("Don‘t Have hide_gesture_line"); } param.setResult(null); } } } ); /*状态更改设置*/ findAndHookMethod("com.android.systemui.statusbar.phone.MiuiDockIndicatorService", "onNavigationModeChanged", int.class, new MethodHook() { @Override protected void before(MethodHookParam param) { XposedHelpers.setObjectField(param.thisObject, "mNavMode", param.args[0]); if (XposedHelpers.getObjectField(param.thisObject, "mNavigationBarView") != null) { XposedHelpers.callMethod(param.thisObject, "setNavigationBarView", (Object) null); } else { XposedHelpers.callMethod(param.thisObject, "checkAndApplyNavigationMode"); } param.setResult(null); } } ); } /*防呆专用*/ public void ContentObserver(Context context) { if (!run) { run = true; ContentObserver contentObserver = new ContentObserver(new Handler(context.getMainLooper())) { @Override public void onChange(boolean z) { boolean language = false; Locale locale = Locale.getDefault(); String languageCode = locale.getLanguage(); if (languageCode.equals("zh")) language = true; Settings.Global.putInt(context.getContentResolver(), "force_fsg_nav_bar", 1); Toast.makeText(context, language ? "请勿切换经典导航键" : "Don't switch navigation keys", Toast.LENGTH_SHORT).show(); XposedLogUtils.logI("Please don't switch classic navigation keys"); } }; context.getContentResolver().registerContentObserver(Settings.Global.getUriFor("force_fsg_nav_bar"), false, contentObserver); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/MiuiGxzwSize.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import com.sevtinge.cemiuiler.module.base.BaseHook; public class MiuiGxzwSize extends BaseHook { @Override public void init() { Class mMiuiGxzwUtils = findClassIfExists("com.android.keyguard.fod.MiuiGxzwUtils"); /*hookAllMethods(mMiuiGxzwUtils,"caculateGxzwIconSize", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { XposedHelpers.setStaticIntField(mMiuiGxzwUtils,"GXZW_ANIM_HEIGHT", 1028); XposedHelpers.setStaticIntField(mMiuiGxzwUtils,"GXZW_ANIM_WIDTH", 1028); } });*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/MonetThemeOverlay.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.content.Context; import android.os.Handler; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.PrefsUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; public class MonetThemeOverlay extends BaseHook { Class THEME_CLASS_AOSP; Context mContext; Handler mHandler; @Override public void init() { THEME_CLASS_AOSP = findClassIfExists("com.android.systemui.theme.ThemeOverlayController"); hookAllConstructors(THEME_CLASS_AOSP, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { mContext = (Context) param.args[0]; /*mHandler = (Handler) param.args[2];*/ } }); hookAllMethods(THEME_CLASS_AOSP, "getOverlay", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { mHandler = new Handler(mContext.getMainLooper()); new PrefsUtils.SharedPrefsObserver(mContext, mHandler, "prefs_key_system_ui_monet_overlay_custom_color", -1) { @Override public void onChange(String name, int defValue) { mPrefsMap.put(name, PrefsUtils.getSharedIntPrefs(mContext, name, defValue)); XposedLogUtils.logI(TAG, name + ": " + PrefsUtils.getSharedIntPrefs(mContext, name, defValue)); } }; param.args[0] = mPrefsMap.getInt("system_ui_monet_overlay_custom_color", -1); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/NotificationFix.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class NotificationFix extends BaseHook { @Override public void init() { XposedHelpers.setStaticBooleanField(XposedHelpers.findClass("com.android.systemui.statusbar.notification.NotificationSettingsManager", lpparam.classLoader), "USE_WHITE_LISTS", false); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/NotificationFreeform.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidU; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class NotificationFreeform extends BaseHook { @Override public void init() { if (isAndroidU()) { findAndHookMethod(findClassIfExists("com.android.systemui.statusbar.notification.row.MiuiExpandableNotificationRow"), "updateMiniWindowBar", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); XposedHelpers.setObjectField(param.thisObject, "mCanSlide", true); } }); } else { findAndHookMethod(findClassIfExists("com.android.systemui.statusbar.notification.NotificationSettingsManager"), "canSlide", String.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/NotificationVolumeSeparateSlider.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import static com.sevtinge.cemiuiler.utils.Helpers.hookAllMethods; import static de.robv.android.xposed.XposedHelpers.findClassIfExists; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.utils.Helpers.MethodHook; import de.robv.android.xposed.XposedHelpers; public class NotificationVolumeSeparateSlider { public static void initHideDeviceControlEntry(ClassLoader pluginLoader) { int notifVolumeOnResId; int notifVolumeOffResId; Class mMiuiVolumeDialogImpl = findClassIfExists("com.android.systemui.miui.volume.MiuiVolumeDialogImpl", pluginLoader); notifVolumeOnResId = XposedInit.mResHook.addResource("ic_miui_volume_notification", R.drawable.ic_miui_volume_notification); notifVolumeOffResId = XposedInit.mResHook.addResource("ic_miui_volume_notification_mute", R.drawable.ic_miui_volume_notification_mute); XposedInit.mResHook.setResReplacement("miui.systemui.plugin", "dimen", "miui_volume_content_width_expanded", R.dimen.miui_volume_content_width_expanded); XposedInit.mResHook.setResReplacement("miui.systemui.plugin", "dimen", "miui_volume_ringer_layout_width_expanded", R.dimen.miui_volume_ringer_layout_width_expanded); XposedInit.mResHook.setResReplacement("miui.systemui.plugin", "dimen", "miui_volume_column_width_expanded", R.dimen.miui_volume_column_width_expanded); XposedInit.mResHook.setResReplacement("miui.systemui.plugin", "dimen", "miui_volume_column_margin_horizontal_expanded", R.dimen.miui_volume_column_margin_horizontal_expanded); hookAllMethods(mMiuiVolumeDialogImpl, "addColumn", new MethodHook() { @Override protected void before(MethodHookParam param) { if (param.args.length != 4) return; int streamType = (int) param.args[0]; if (streamType == 4) { XposedHelpers.callMethod(param.thisObject, "addColumn", 5, notifVolumeOnResId, notifVolumeOffResId, true, false); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/OriginChargeAnimation.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; public class OriginChargeAnimation extends BaseHook { Class mOriginChargeAnimCls; @Override public void init() { mOriginChargeAnimCls = findClassIfExists("com.android.systemui.statusbar.FeatureFlags"); findAndHookMethod(mOriginChargeAnimCls, "isChargingRippleEnabled", new Helpers.MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { param.setResult(true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/QSDetailBackGround.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.content.pm.ApplicationInfo; import android.graphics.Paint; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import de.robv.android.xposed.XposedHelpers; public class QSDetailBackGround extends BaseHook { private ClassLoader mPluginLoader = null; @Override public void init() { findAndHookMethod("com.android.systemui.shared.plugins.PluginManagerImpl", "getClassLoader", ApplicationInfo.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ApplicationInfo appInfo = (ApplicationInfo) param.args[0]; if ("miui.systemui.plugin".equals(appInfo.packageName)) { if (mPluginLoader == null) { mPluginLoader = (ClassLoader) param.getResult(); } Helpers.hookAllMethods("miui.systemui.widget.SmoothRoundDrawable", mPluginLoader, "inflate", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Paint mPaint = (Paint) XposedHelpers.getObjectField(param.thisObject, "mPaint"); mPaint.setAlpha(mPrefsMap.getInt("system_control_center_qs_detail_bg", 0)); } }); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/QSLabelsHook.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.content.pm.ApplicationInfo; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class QSLabelsHook extends BaseHook { final boolean[] isHooked = {false}; private static ClassLoader pluginLoader = null; Class mQSController; @Override public void init() { findAndHookMethod("com.android.systemui.shared.plugins.PluginManagerImpl", "getClassLoader", ApplicationInfo.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ApplicationInfo appInfo = (ApplicationInfo) param.args[0]; if ("miui.systemui.plugin".equals(appInfo.packageName) && !isHooked[0]) { isHooked[0] = true; if (pluginLoader == null) { pluginLoader = (ClassLoader) param.getResult(); } mQSController = XposedHelpers.findClassIfExists("miui.systemui.controlcenter.qs.tileview.StandardTileView", pluginLoader); hookAllMethods(mQSController, "init", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { if (param.args.length != 1) return; View mLabelContainer = (View) XposedHelpers.getObjectField(param.thisObject, "labelContainer"); if (mLabelContainer != null) { mLabelContainer.setVisibility( mPrefsMap.getBoolean("system_ui_qs_label") ? View.GONE : View.VISIBLE ); } } }); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/ShouldPlayUnmuteSoundHook.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import de.robv.android.xposed.XposedHelpers; public class ShouldPlayUnmuteSoundHook extends BaseHook { Class mQuietModeTile = XposedHelpers.findClassIfExists("com.android.systemui.qs.tiles.QuietModeTile", lpparam.classLoader); Class mZenModeController = XposedHelpers.findClassIfExists("com.android.systemui.statusbar.policy.ZenModeController", lpparam.classLoader); @Override public void init() { Helpers.findAndHookMethod(mQuietModeTile, "handleClick", View.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { XposedHelpers.setBooleanField(mZenModeController, "isZenModeOn", true); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/StatusBarActions.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.Process; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; public class StatusBarActions extends BaseHook { Class mStatusBarClass; public static Object mStatusBar = null; @Override public void init() { if (isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU)) { mStatusBarClass = findClassIfExists("com.android.systemui.statusbar.phone.CentralSurfacesImpl"); } else { mStatusBarClass = findClassIfExists("com.android.systemui.statusbar.phone.StatusBar"); } setupStatusBarAction(); setupRestartSystemUIAction(); } // StatusBarActions public void setupStatusBarAction() { findAndHookMethod(mStatusBarClass, "start", new MethodHook() { @Override protected void after(MethodHookParam param) { mStatusBar = param.thisObject; Context mStatusBarContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); IntentFilter intentfilter = new IntentFilter(); intentfilter.addAction(ACTION_PREFIX + "OpenNotificationCenter"); intentfilter.addAction(ACTION_PREFIX + "ExpandSettings"); intentfilter.addAction(ACTION_PREFIX + "OpenRecents"); intentfilter.addAction(ACTION_PREFIX + "OpenVolumeDialog"); intentfilter.addAction(ACTION_PREFIX + "ToggleGPS"); intentfilter.addAction(ACTION_PREFIX + "ToggleHotspot"); intentfilter.addAction(ACTION_PREFIX + "ToggleFlashlight"); intentfilter.addAction(ACTION_PREFIX + "ShowQuickRecents"); intentfilter.addAction(ACTION_PREFIX + "HideQuickRecents"); intentfilter.addAction(ACTION_PREFIX + "ClearMemory"); intentfilter.addAction(ACTION_PREFIX + "CollectXposedLog"); intentfilter.addAction(ACTION_PREFIX + "RestartLauncher"); intentfilter.addAction(ACTION_PREFIX + "CopyToExternal"); mStatusBarContext.registerReceiver(mStatusBarReceiver, intentfilter); } }); } private static final BroadcastReceiver mStatusBarReceiver = new BroadcastReceiver() { @SuppressLint("WrongConstant") @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action == null) return; switch (action) { case ACTION_PREFIX + "ClearMemory" -> { Intent clearIntent = new Intent("com.android.systemui.taskmanager.Clear"); clearIntent.putExtra("show_toast", true); // clearIntent.putExtra("clean_type", -1); context.sendBroadcast(clearIntent); } case ACTION_PREFIX + "OpenRecents" -> { Intent recentIntent = new Intent("SYSTEM_ACTION_RECENTS"); recentIntent.setPackage("com.android.systemui"); context.sendBroadcast(recentIntent); } case ACTION_PREFIX + "OpenVolumeDialog" -> OpenVolumeDialogs(context); case ACTION_PREFIX + "OpenNotificationCenter" -> { try { Object mNotificationPanel = XposedHelpers.getObjectField(mStatusBar, "mNotificationPanel"); boolean mPanelExpanded = (boolean) XposedHelpers.getObjectField(mNotificationPanel, "mPanelExpanded"); boolean mQsExpanded = (boolean) XposedHelpers.getObjectField(mNotificationPanel, "mQsExpanded"); boolean expandOnly = intent.getBooleanExtra("expand_only", false); if (mPanelExpanded) { if (!expandOnly) { if (mQsExpanded) { XposedHelpers.callMethod(mStatusBar, "closeQs"); } else { XposedHelpers.callMethod(mStatusBar, "animateCollapsePanels"); } } } else { XposedHelpers.callMethod(mStatusBar, "animateExpandNotificationsPanel"); } } catch (Throwable t) { // Expand only long token = Binder.clearCallingIdentity(); XposedHelpers.callMethod(context.getSystemService("statusbar"), "expandNotificationsPanel"); Binder.restoreCallingIdentity(token); } } } } }; public static void OpenVolumeDialogs(Context context) { try { Object mVolumeComponent = XposedHelpers.getObjectField(mStatusBar, "mVolumeComponent"); Object mVolumeDialogPlugin = XposedHelpers.getObjectField(mVolumeComponent, "mDialog"); Object miuiVolumeDialog = XposedHelpers.getObjectField(mVolumeDialogPlugin, "mVolumeDialogImpl"); if (miuiVolumeDialog == null) { XposedLogUtils.logI("OpenVolumeDialog", "MIUI volume dialog is NULL!"); return; } Handler mHandler = (Handler) XposedHelpers.getObjectField(miuiVolumeDialog, "mHandler"); mHandler.post(() -> { boolean mShowing = XposedHelpers.getBooleanField(miuiVolumeDialog, "mShowing"); boolean mExpanded = XposedHelpers.getBooleanField(miuiVolumeDialog, "mExpanded"); AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); boolean isInCall = am.getMode() == AudioManager.MODE_IN_CALL || am.getMode() == AudioManager.MODE_IN_COMMUNICATION; if (mShowing) { if (mExpanded || isInCall) XposedHelpers.callMethod(miuiVolumeDialog, "dismissH", 1); else { Object mDialogView = XposedHelpers.getObjectField(miuiVolumeDialog, "mDialogView"); View mExpandButton = (View) XposedHelpers.getObjectField(mDialogView, "mExpandButton"); View.OnClickListener mClickExpand = (View.OnClickListener) XposedHelpers.getObjectField(mDialogView, "expandListener"); mClickExpand.onClick(mExpandButton); } } else { Object mController = XposedHelpers.getObjectField(mVolumeDialogPlugin, "mController"); if (isInCall) { XposedHelpers.callMethod(mController, "setActiveStream", 0); XposedHelpers.setBooleanField(miuiVolumeDialog, "mNeedReInit", true); } else if (am.isMusicActive()) { XposedHelpers.callMethod(mController, "setActiveStream", 3); XposedHelpers.setBooleanField(miuiVolumeDialog, "mNeedReInit", true); } XposedHelpers.callMethod(miuiVolumeDialog, "showH", 1); } }); } catch (Throwable t) { XposedBridge.log(t); } } public void setupRestartSystemUIAction() { if (mStatusBarClass == null) return; findAndHookMethod(mStatusBarClass, "start", new MethodHook() { @Override protected void after(MethodHookParam param) { mStatusBar = param.thisObject; Context mStatusBarContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); IntentFilter intentfilter = new IntentFilter(); intentfilter.addAction(ACTION_PREFIX + "RestartSystemUI"); mStatusBarContext.registerReceiver(mRestartSystemUIReceiver, intentfilter); } }); } private final BroadcastReceiver mRestartSystemUIReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action == null) return; if (action.equals(ACTION_PREFIX + "RestartSystemUI")) { Process.sendSignal(Process.myPid(), Process.SIGNAL_KILL); } } }; } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/SwitchControlPanel.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogI; import android.view.MotionEvent; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class SwitchControlPanel extends BaseHook { Class mControlPanelWindowManager; @Override public void init() { mControlPanelWindowManager = findClassIfExists("com.android.systemui.controlcenter.phone.ControlPanelWindowManager"); findAndHookMethod(mControlPanelWindowManager, "dispatchToControlPanel", MotionEvent.class, float.class, new MethodHook() { @Override protected void before(MethodHookParam param) { float f = (float) param.args[1]; XposedHelpers.setFloatField(param.thisObject, "mDownX", f); float mDownX = XposedHelpers.getFloatField(param.thisObject, "mDownX"); int i = (Float.compare(mDownX, f / 2.0f)); LogI(TAG, "mDownX:" + mDownX + "in before"); LogI(TAG, "f:" + f + "in before"); LogI(TAG, ":" + i + "in before"); i *= -1; int i2 = i; LogI(TAG, ":" + i2 + "in before"); } @Override protected void after(MethodHookParam param) { float mDownX = XposedHelpers.getFloatField(param.thisObject, "mDownX"); float f = (float) param.args[1]; int i = (Float.compare(mDownX, f / 2.0f)); LogI(TAG, "mDownX:" + mDownX + "in after"); LogI(TAG, "f:" + f + "in after"); LogI(TAG, ":" + i + "in after"); i *= -1; int i2 = i; LogI(TAG, ":" + i2 + "in after"); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/UseNativeRecents.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; public class UseNativeRecents { } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/VolumeTimerValuesHook.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui; import android.content.Context; import android.content.pm.ApplicationInfo; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import de.robv.android.xposed.XposedHelpers; public class VolumeTimerValuesHook extends BaseHook { private static ClassLoader pluginLoader = null; @Override public void init() { /*VolumeTimerValuesRes();*/ final boolean[] isHooked = {false}; Helpers.findAndHookMethod("com.android.systemui.shared.plugins.PluginManagerImpl", lpparam.classLoader, "getClassLoader", ApplicationInfo.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ApplicationInfo appInfo = (ApplicationInfo) param.args[0]; if ("miui.systemui.plugin".equals(appInfo.packageName) && !isHooked[0]) { isHooked[0] = true; if (pluginLoader == null) { pluginLoader = (ClassLoader) param.getResult(); } Helpers.findAndHookMethod("com.android.systemui.miui.volume.MiuiVolumeTimerDrawableHelper", pluginLoader, "initTimerString", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); String[] mTimeSegmentTitle = new String[11]; int timerOffId = mContext.getResources().getIdentifier("timer_off", "string", "miui.systemui.plugin"); int minuteId = mContext.getResources().getIdentifier("timer_30_minutes", "string", "miui.systemui.plugin"); int hourId = mContext.getResources().getIdentifier("timer_1_hour", "string", "miui.systemui.plugin"); mTimeSegmentTitle[0] = mContext.getResources().getString(timerOffId); mTimeSegmentTitle[1] = mContext.getResources().getString(minuteId, 30); mTimeSegmentTitle[2] = mContext.getResources().getString(hourId, 1); mTimeSegmentTitle[3] = mContext.getResources().getString(hourId, 2); mTimeSegmentTitle[4] = mContext.getResources().getString(hourId, 3); mTimeSegmentTitle[5] = mContext.getResources().getString(hourId, 4); mTimeSegmentTitle[6] = mContext.getResources().getString(hourId, 5); mTimeSegmentTitle[7] = mContext.getResources().getString(hourId, 6); mTimeSegmentTitle[8] = mContext.getResources().getString(hourId, 8); mTimeSegmentTitle[9] = mContext.getResources().getString(hourId, 10); mTimeSegmentTitle[10] = mContext.getResources().getString(hourId, 12); XposedHelpers.setObjectField(param.thisObject, "mTimeSegmentTitle", mTimeSegmentTitle); } }); Helpers.findAndHookMethod("com.android.systemui.miui.volume.TimerItem", pluginLoader, "getTimePos", int.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Object timer = XposedHelpers.getObjectField(param.thisObject, "mTimerTime"); float halfTimerWidth = ((int) XposedHelpers.callMethod(timer, "getWidth")) / 2.0f; Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); float seekWidth = mContext.getResources().getDimension(mContext.getResources().getIdentifier("miui_volume_timer_seelbar_width", "dimen", "miui.systemui.plugin")); int marginLeft = mContext.getResources().getDimensionPixelSize(mContext.getResources().getIdentifier("miui_volume_timer_seekbar_margin_left", "dimen", "miui.systemui.plugin")); int seg = (int) XposedHelpers.getObjectField(param.thisObject, "mDeterminedSegment"); param.setResult(seekWidth / 10 * seg + marginLeft - halfTimerWidth); } }); } } }); } /*public static void VolumeTimerValuesRes() { XposedInit.mResourcesHook.setResReplacement("miui.systemui.plugin", "array", "miui_volume_timer_segments", R.array.miui_volume_timer_segments); }*/ } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/AddBlurEffectToNotificationView.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.graphics.drawable.Drawable import android.graphics.drawable.GradientDrawable import android.view.View import android.view.ViewGroup import com.github.kyuubiran.ezxhelper.EzXHelper.appContext import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.HookUtils import com.sevtinge.cemiuiler.utils.callStaticMethod import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidS import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidT import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidU import com.sevtinge.cemiuiler.utils.devicesdk.isMoreAndroidVersion import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.hookAfterMethod import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import com.sevtinge.cemiuiler.utils.replaceMethod import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers object AddBlurEffectToNotificationView : BaseHook() { var blurBackgroundAlpha: Int = mPrefsMap.getInt("system_ui_control_center_blur_background_alpha", 100) var cornerRadius: Int = mPrefsMap.getInt("system_ui_control_center_corner_radius", 48) var blurRadius: Int = mPrefsMap.getInt("system_ui_control_center_blur_radius", 99) var defaultBackgroundAlpha: Int = mPrefsMap.getInt("system_ui_control_center_default_background_alpha", 200) val fixNotification by lazy { mPrefsMap.getBoolean("n_enable_fix") } fun setDrawableAlpha(thiz: Any?, alpha: Int) { if (isAndroidU()) { XposedHelpers.setObjectField(thiz, "mDrawableAlpha", alpha) } else { XposedHelpers.callMethod( thiz, "setDrawableAlpha", arrayOf>(Integer.TYPE), alpha ) } } override fun init() { val miuiExpandableNotificationRowClass = findClassIfExists("com.android.systemui.statusbar.notification.row.MiuiExpandableNotificationRow") ?: return val notificationBackgroundViewClass = findClassIfExists("com.android.systemui.statusbar.notification.row.NotificationBackgroundView") ?: return val appMiniWindowRowTouchHelperClass = findClassIfExists("com.android.systemui.statusbar.notification.policy.AppMiniWindowRowTouchHelper") ?: return val miuiNotificationPanelViewControllerClass = findClassIfExists( if (isAndroidU()) "com.android.systemui.shade.MiuiNotificationPanelViewController" else "com.android.systemui.statusbar.phone.MiuiNotificationPanelViewController" ) ?: return val notificationStackScrollLayoutClass = findClassIfExists("com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout") ?: return val lockScreenMagazineControllerClass = findClassIfExists("com.android.keyguard.magazine.LockScreenMagazineController") ?: return val blurRatioChangedListener = findClassIfExists( if (isAndroidU()) "com.android.systemui.shade.MiuiNotificationPanelViewController\$mBlurRatioChangedListener\$1" else "com.android.systemui.statusbar.phone.MiuiNotificationPanelViewController\$mBlurRatioChangedListener\$1" ) ?: return // 通知模糊额外修正项,增加一个开关避免使用过程中暴毙 if (isAndroidT() && fixNotification) { val mediaDataFilterClass = findClassIfExists("com.android.systemui.media.MediaDataFilter") ?: return val expandableNotificationRowClass = findClassIfExists("com.android.systemui.statusbar.notification.row.ExpandableNotificationRow") ?: return // 增加一个锁屏页面判断 var onKeyguard = false expandableNotificationRowClass.hookAfterMethod("isOnKeyguard") { onKeyguard = it.result as Boolean } // 增加一个控制中心音乐播放器判断 var hasActiveMediaOrRecommendation = false mediaDataFilterClass.hookAfterMethod("hasActiveMediaOrRecommendation") { hasActiveMediaOrRecommendation = it.result as Boolean } // 换个方式修改通知上划极限值 try { "com.android.systemui.statusbar.notification.stack.AmbientState".replaceMethod("getOverExpansion") { val getScreenHeight = findClass("com.android.systemui.fsgesture.AppQuickSwitchActivity") .callStaticMethod("getScreenHeight", appContext) as Int val mOverExpansion = it.thisObject.getObjectField("mOverExpansion") as Float val isNCSwitching = it.thisObject.getObjectField("isNCSwitching") as Boolean val isSwipingUp = it.thisObject.getObjectField("mIsSwipingUp") as Boolean val isFlinging = it.thisObject.getObjectField("mIsFlinging") as Boolean val isAppearing = it.thisObject.getObjectField("mAppearing") as Boolean val isScreenLandscape = findClass("com.android.systemui.statusbar.notification.NotificationUtil") .callStaticMethod("isScreenLandscape") as Boolean if (isAppearing && (isSwipingUp || isFlinging) && !isNCSwitching) { if (hasActiveMediaOrRecommendation) { if (isScreenLandscape) return@replaceMethod -getScreenHeight.toFloat() else return@replaceMethod -getScreenHeight.toFloat() * 6.0f } else { if (isScreenLandscape) return@replaceMethod -getScreenHeight.toFloat() / 3.0f else return@replaceMethod -getScreenHeight.toFloat() / 1.2f } } else { return@replaceMethod mOverExpansion } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } try { "com.android.systemui.statusbar.notification.stack.AmbientState".replaceMethod("getAppearFraction") { val isNCSwitching = it.thisObject.getObjectField("isNCSwitching") as Boolean val isSwipingUp = it.thisObject.getObjectField("mIsSwipingUp") as Boolean val isFlinging = it.thisObject.getObjectField("mIsFlinging") as Boolean val mAppearFraction = it.thisObject.getObjectField("mAppearFraction") as Float val isAppearing = it.thisObject.getObjectField("mAppearing") as Boolean val isScreenLandscape = findClass("com.android.systemui.statusbar.notification.NotificationUtil") .callStaticMethod("isScreenLandscape") as Boolean if (isAppearing && (isSwipingUp || isFlinging) && !isNCSwitching && hasActiveMediaOrRecommendation && isScreenLandscape) { return@replaceMethod mAppearFraction * 6.0f } else { return@replaceMethod mAppearFraction } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } } // 每次设置背景的时候都同时改透明度 XposedBridge.hookAllMethods( notificationBackgroundViewClass, "setCustomBackground", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val notificationBackgroundView = param.thisObject val mDrawableAlphaField = notificationBackgroundViewClass.getDeclaredField("mDrawableAlpha") mDrawableAlphaField.isAccessible = true val isHandsUp = XposedHelpers.callMethod(notificationBackgroundView, "headsUp") as Boolean if (isHandsUp) { mDrawableAlphaField.set(notificationBackgroundView, blurBackgroundAlpha) setDrawableAlpha( notificationBackgroundView, blurBackgroundAlpha ) } else { mDrawableAlphaField.set(notificationBackgroundView, defaultBackgroundAlpha) setDrawableAlpha( notificationBackgroundView, defaultBackgroundAlpha ) } } }) // 背景bounds改动同步到模糊 XposedBridge.hookAllMethods( notificationBackgroundViewClass, "draw", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val notificationBackground = param.thisObject as View val backgroundDrawable = notificationBackground.background ?: return // 适配游戏模式及横屏全屏视频半透明通知(可以做个开关) if (isTransparentAble() && fixNotification) { XposedHelpers.callMethod( notificationBackground.background, "setVisible", false, false ) } else { XposedHelpers.callMethod( notificationBackground.background, "setVisible", true, false ) } if (HookUtils.isBlurDrawable(backgroundDrawable)) { val drawable = param.args[1] as Drawable backgroundDrawable.bounds = drawable.bounds } } }) // 进入小窗模式的时候把模糊去掉 XposedBridge.hookAllMethods( appMiniWindowRowTouchHelperClass, "onMiniWindowTrackingStart", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { val mPickedMiniWindowChild = HookUtils.getValueByField(param.thisObject, "mPickedMiniWindowChild") ?: return val mBackgroundNormal = HookUtils.getValueByField(mPickedMiniWindowChild, "mBackgroundNormal") ?: return mBackgroundNormal as View if (HookUtils.isBlurDrawable(mBackgroundNormal.background)) { XposedHelpers.callMethod( mBackgroundNormal.background, "setVisible", false, false ) setDrawableAlpha( mBackgroundNormal, defaultBackgroundAlpha + 30 ) } } }) XposedBridge.hookAllMethods( appMiniWindowRowTouchHelperClass, "onMiniWindowReset", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { val mPickedMiniWindowChild = HookUtils.getValueByField(param.thisObject, "mPickedMiniWindowChild") ?: return val mBackgroundNormal = HookUtils.getValueByField(mPickedMiniWindowChild, "mBackgroundNormal") ?: return mBackgroundNormal as View if (HookUtils.isBlurDrawable(mBackgroundNormal.background)) { XposedHelpers.callMethod( mBackgroundNormal.background, "setVisible", true, false ) setDrawableAlpha( mBackgroundNormal, blurBackgroundAlpha ) } } }) // 悬浮的时候把模糊加上 XposedBridge.hookAllMethods( miuiExpandableNotificationRowClass, "setHeadsUp", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { val isHeadsUp = param.args[0] as Boolean val miuiNotificationBackgroundView = param.thisObject as View val mBackgroundNormal = HookUtils.getValueByField( miuiNotificationBackgroundView, "mBackgroundNormal" ) as View if (!mBackgroundNormal.isAttachedToWindow) { return } if (isHeadsUp) { if (mBackgroundNormal.background != null) { if (HookUtils.isBlurDrawable(mBackgroundNormal.background)) { return } } mBackgroundNormal.background = HookUtils.createBlurDrawable( mBackgroundNormal, blurRadius, cornerRadius ) setDrawableAlpha( mBackgroundNormal, blurBackgroundAlpha ) } /*else { if (HookUtils.isBlurDrawable(mBackgroundNormal.background)) { mBackgroundNormal.background = null } try { XposedHelpers.callMethod( mBackgroundNormal, "setDrawableAlpha", defaultBackgroundAlpha ) } catch (e: Throwable) { logE("BlurNotificationView -> defaultBackgroundAlpha", e) } }*/ } }) // 进入不同状态,处理一下模糊 XposedBridge.hookAllMethods( miuiNotificationPanelViewControllerClass, "onStateChanged", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { // status 1 锁屏 2 锁屏下拉 0 其他 val status = param.args[0] as Int val mNotificationStackScroller = HookUtils.getValueByField( param.thisObject, "mNotificationStackScroller" ) as ViewGroup if (status == 1) { if (!isDefaultLockScreenTheme()) { return } for (i in 0..mNotificationStackScroller.childCount) { val childAt = mNotificationStackScroller.getChildAt(i) ?: continue showBlurEffectForNotificationRow(childAt) } } else { for (i in 0..mNotificationStackScroller.childCount) { val childAt = mNotificationStackScroller.getChildAt(i) ?: continue try { val isHeadsUp = XposedHelpers.callMethod(childAt, "isHeadsUpState") as Boolean val isPinned = XposedHelpers.callMethod( childAt, "isPinned" ) as Boolean if (isHeadsUp && isPinned) { showBlurEffectForNotificationRow(childAt) } else { hideBlurEffectForNotificationRow(childAt) } } catch (e: Throwable) { hideBlurEffectForNotificationRow(childAt) } } } } }) // 下拉完成处理模糊 /* XposedBridge.hookAllMethods( NotificationPanelViewControllerClass, "onExpandingFinished", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val isOnKeyguard = XposedHelpers.callMethod(param.thisObject, "isOnKeyguard") as Boolean if (isOnKeyguard) { return } val mNotificationStackScroller = Hook.getValueByField( param.thisObject, "mNotificationStackScroller" ) ?: return mNotificationStackScroller as ViewGroup for (i in 0..mNotificationStackScroller.childCount) { val childAt = mNotificationStackScroller.getChildAt(i) ?: continue hideBlurEffectForNotificationRow(childAt) } } }) */ // 通知添加进视图的时候增加模糊 XposedBridge.hookAllMethods( notificationStackScrollLayoutClass, "onViewAddedInternal", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val expandableView = param.args[0] as View val mController = HookUtils.getValueByField(param.thisObject, "mController") ?: return val mPanelViewController = HookUtils.getValueByField(mController, "mPanelViewController") ?: return val isExpanding = XposedHelpers.callMethod( mPanelViewController, if (isAndroidU()) "isExpandingOrCollapsing" else "isExpanding" ) as Boolean if (isExpanding) return val isOnKeyguard = XposedHelpers.callMethod(mPanelViewController, "isOnKeyguard") as Boolean if (isOnKeyguard) { if (!isDefaultLockScreenTheme()) { return } showBlurEffectForNotificationRow(expandableView) } else { // ZenModeView 没有 isHeadsUpState 方法 try { val isHeadsUp = XposedHelpers.callMethod( expandableView, "isHeadsUpState" ) as Boolean if (isHeadsUp) { showBlurEffectForNotificationRow(expandableView) } } catch (e: Throwable) { return } } } }) // 锁屏状态透明度修改的时候同步修改模糊透明度 if (isAndroidS()) { XposedBridge.hookAllMethods(miuiNotificationPanelViewControllerClass, "updateKeyguardElementAlpha", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) return val mNotificationStackScroller = HookUtils.getValueByField( param.thisObject, "mNotificationStackScroller" ) ?: return mNotificationStackScroller as ViewGroup val keyguardContentsAlpha = XposedHelpers.callMethod( param.thisObject, "getKeyguardContentsAlpha" ) as Float val drawableAlpha = keyguardContentsAlpha * 255 for (i in 0..mNotificationStackScroller.childCount) { val childAt = mNotificationStackScroller.getChildAt(i) ?: continue setBlurEffectAlphaForNotificationRow(childAt, drawableAlpha.toInt()) } } }) } XposedBridge.hookAllMethods( miuiNotificationPanelViewControllerClass, "onBouncerShowingChanged", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { val isBouncerShowing = param.args[0] as Boolean val mNotificationStackScroller = HookUtils.getValueByField(param.thisObject, "mNotificationStackScroller") ?: return mNotificationStackScroller as ViewGroup for (i in 0..mNotificationStackScroller.childCount) { val childAt = mNotificationStackScroller.getChildAt(i) ?: continue if (isBouncerShowing) { hideBlurEffectForNotificationRow(childAt) } else { showBlurEffectForNotificationRow(childAt) } } } }) if (isMoreAndroidVersion(33)) { // 锁屏画报 隐藏模糊 // 修复 Android 13 锁屏画报模糊残留 XposedBridge.hookAllMethods( lockScreenMagazineControllerClass, "setPanelViewAlpha", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) return val alpha = param.args[0] as Float val drawableAlpha = alpha * 255 val mNotificationStackScrollLayoutController = HookUtils.getValueByField( param.thisObject, "mNotificationStackScrollLayoutController" ) ?: return val mView = HookUtils.getValueByField( mNotificationStackScrollLayoutController, "mView" ) ?: return mView as ViewGroup for (i in 0..mView.childCount) { val childAt = mView.getChildAt(i) ?: continue setBlurEffectAlphaForNotificationRow(childAt, drawableAlpha.toInt()) } } }) } else { // 锁屏画报 隐藏模糊 XposedBridge.hookAllMethods( lockScreenMagazineControllerClass, "setViewsAlpha", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) return val alpha = param.args[0] as Float val drawableAlpha = alpha * 255 val mNotificationStackScrollLayout = HookUtils.getValueByField( param.thisObject, "mNotificationStackScrollLayout" ) as ViewGroup for (i in 0..mNotificationStackScrollLayout.childCount) { val childAt = mNotificationStackScrollLayout.getChildAt(i) ?: continue setBlurEffectAlphaForNotificationRow(childAt, drawableAlpha.toInt()) } } }) } XposedBridge.hookAllMethods( notificationStackScrollLayoutClass, "setDozing", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val isDozing = param.args[0] as Boolean val mNotificationStackScrollLayout = param.thisObject as ViewGroup for (i in 0..mNotificationStackScrollLayout.childCount) { val childAt = mNotificationStackScrollLayout.getChildAt(i) ?: continue if (isDozing) { hideBlurEffectForNotificationRow(childAt) } else { showBlurEffectForNotificationRow(childAt) } } } }) /* XposedBridge.hookAllMethods( KeyguardPanelViewInjectorClass, "onKeyguardVisibilityChanged", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val isVisible = param.args[0] as Boolean val mPanelViewController = Hook.getValueByField(param.thisObject, "mPanelViewController") ?: return val mNotificationStackScroller = Hook.getValueByField( mPanelViewController, "mNotificationStackScroller" ) ?: return mNotificationStackScroller as ViewGroup for (i in 0..mNotificationStackScroller.childCount) { val childAt = mNotificationStackScroller.getChildAt(i) ?: continue if (isVisible) { showBlurEffectForNotificationRow(childAt) } else { try { val isHeadsUp = XposedHelpers.callMethod( childAt, "isHeadsUpState" ) as Boolean val isPinned = XposedHelpers.callMethod( childAt, "isPinned" ) as Boolean if (isHeadsUp && isPinned) { showBlurEffectForNotificationRow(childAt) } else { hideBlurEffectForNotificationRow(childAt) } } catch (e: Throwable) { hideBlurEffectForNotificationRow(childAt) } } } } }) */ XposedBridge.hookAllConstructors(miuiNotificationPanelViewControllerClass, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val mNotificationStackScroller = HookUtils.getValueByField( param.thisObject, "mNotificationStackScroller" ) ?: return mNotificationStackScroller as ViewGroup XposedBridge.hookAllMethods(blurRatioChangedListener, "onBlurRadiusChanged", object : XC_MethodHook() { override fun afterHookedMethod(params: MethodHookParam) { val radius = params.args[0] as Int val isOnKeyguard = XposedHelpers.callMethod( param.thisObject, "isOnKeyguard" ) as Boolean for (i in 0..mNotificationStackScroller.childCount) { val childAt = mNotificationStackScroller.getChildAt(i) ?: continue if (radius > 30 && !isOnKeyguard) { hideBlurEffectForNotificationRow(childAt) } /*else { // 锁屏状态显示模糊(不能留,点击通知进入密码页面模糊残留) if (isOnKeyguard) showBlurEffectForNotificationRow(childAt) }*/ } } }) } }) } fun isDefaultLockScreenTheme(): Boolean { val miuiKeyguardUtilsClass = findClassIfExists( if (isAndroidU()) "com.miui.systemui.util.CommonUtil" else "com.android.keyguard.utils.MiuiKeyguardUtils" ) ?: return true return XposedHelpers.callStaticMethod( miuiKeyguardUtilsClass, "isDefaultLockScreenTheme" ) as Boolean } // 增加一个游戏模式跟全屏视频判断,用以增加透明通知适配 fun isTransparentAble(): Boolean { val notificationContentInflaterInjectorClass = findClassIfExists( "com.android.systemui.statusbar.notification.row.NotificationContentInflaterInjector" ) ?: return true return XposedHelpers.callStaticMethod( notificationContentInflaterInjectorClass, "isTransparentAble" ) as Boolean } fun hideBlurEffectForNotificationRow(notificationRow: View) { if (notificationRow.javaClass.name.contains("ZenModeView")) { val zenModeContentContainer = XposedHelpers.callMethod(notificationRow, "getContentView") ?: return zenModeContentContainer as ViewGroup val zenModeContent = zenModeContentContainer.getChildAt(0) ?: return val contentBackground = zenModeContent.background as GradientDrawable contentBackground.alpha = defaultBackgroundAlpha contentBackground.invalidateSelf() if (HookUtils.isBlurDrawable(zenModeContentContainer.background)) { zenModeContentContainer.background = null } } else { val mBackgroundNormal = HookUtils.getValueByField(notificationRow, "mBackgroundNormal") ?: return mBackgroundNormal as View if (HookUtils.isBlurDrawable(mBackgroundNormal.background)) { mBackgroundNormal.background = null } runCatching { setDrawableAlpha( mBackgroundNormal, defaultBackgroundAlpha ) } runCatching { val childList = XposedHelpers.callMethod(notificationRow, "getAttachedChildren") ?: return childList as List<*> if (childList.size > 0) { childList.forEach { child -> if (child != null) { hideBlurEffectForNotificationRow(child as View) } } } } } } fun setBlurEffectAlphaForNotificationRow(notificationRow: View, alpha: Int) { if (alpha < 0 || alpha > 255) { return } if (notificationRow.javaClass.name.contains("ZenModeView")) { val zenModeContentContainer = XposedHelpers.callMethod(notificationRow, "getContentView") ?: return zenModeContentContainer as ViewGroup if (HookUtils.isBlurDrawable(zenModeContentContainer.background)) { XposedHelpers.callMethod(zenModeContentContainer.background, "setAlpha", alpha) } } else { val mBackgroundNormal = HookUtils.getValueByField(notificationRow, "mBackgroundNormal") ?: return mBackgroundNormal as View if (HookUtils.isBlurDrawable(mBackgroundNormal.background)) { XposedHelpers.callMethod(mBackgroundNormal.background, "setAlpha", alpha) } runCatching { val childList = XposedHelpers.callMethod(notificationRow, "getAttachedChildren") ?: return childList as List<*> if (childList.size > 0) { childList.forEach { child -> if (child != null) { setBlurEffectAlphaForNotificationRow(child as View, alpha) } } } } } } fun showBlurEffectForNotificationRow(notificationRow: View) { if (notificationRow.javaClass.name.contains("ZenModeView")) { val zenModeContentContainer = XposedHelpers.callMethod(notificationRow, "getContentView") ?: return zenModeContentContainer as ViewGroup val zenModeContent = zenModeContentContainer.getChildAt(0) ?: return val contentBackground = zenModeContent.background as GradientDrawable contentBackground.alpha = blurBackgroundAlpha contentBackground.invalidateSelf() if (!HookUtils.isBlurDrawable(zenModeContentContainer.background)) { zenModeContentContainer.background = HookUtils.createBlurDrawable(notificationRow, blurRadius, cornerRadius) } } else { val mBackgroundNormal = HookUtils.getValueByField(notificationRow, "mBackgroundNormal") ?: return mBackgroundNormal as View if (!HookUtils.isBlurDrawable(mBackgroundNormal.background)) { mBackgroundNormal.background = HookUtils.createBlurDrawable(mBackgroundNormal, blurRadius, cornerRadius) runCatching { setDrawableAlpha( mBackgroundNormal, blurBackgroundAlpha ) } } runCatching { val childList = XposedHelpers.callMethod(notificationRow, "getAttachedChildren") ?: return childList as List<*> if (childList.size > 0) { childList.forEach { child -> if (child != null) { showBlurEffectForNotificationRow(child as View) } } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/BluetoothTileStyle.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import static com.sevtinge.cemiuiler.module.base.BaseXposedInit.mPrefsMap; import static com.sevtinge.cemiuiler.utils.devicesdk.AppUtilsKt.dp2px2; import android.annotation.SuppressLint; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.Helpers.MethodHook; import com.sevtinge.cemiuiler.utils.ResourcesHook; import java.util.ArrayList; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; public class BluetoothTileStyle { public static void initHideDeviceControlEntry(ClassLoader pluginLoader) { int styleId = mPrefsMap.getStringAsInt("system_ui_control_center_cc_bluetooth_tile_style", 1); if (styleId == 1) return; final int[] tileResIds = {0}; Helpers.findAndHookMethod("miui.systemui.dagger.PluginComponentFactory", pluginLoader, "create", Context.class, Context.class, new MethodHook() { @SuppressLint("DiscouragedApi") protected void after(XC_MethodHook.MethodHookParam param) { Context pluginContext = (Context) param.args[1]; tileResIds[0] = pluginContext.getResources().getIdentifier("big_tile", "layout", "miui.systemui.plugin"); } }); Helpers.hookAllMethods("miui.systemui.controlcenter.dagger.ControlCenterViewModule", pluginLoader, "createBigTileGroup", new MethodHook() { @Override protected void after(XC_MethodHook.MethodHookParam param) { ViewGroup mView = (ViewGroup) param.getResult(); LayoutInflater li = (LayoutInflater) XposedHelpers.callMethod(param.args[0], "injectable", param.args[1]); View btTileView = li.inflate(tileResIds[0], null); mView.addView(btTileView, 2); btTileView.setTag("big_tile_bt"); } }); MethodHook updateStyleHook = new MethodHook() { boolean United = false; @Override @SuppressLint("DiscouragedApi") protected void after(XC_MethodHook.MethodHookParam param) throws Throwable { ViewGroup mView = (ViewGroup) XposedHelpers.callMethod(param.thisObject, "getView"); View bigTileB = (View) XposedHelpers.getObjectField(param.thisObject, "bigTileB"); if (!United) { United = true; Object factory = XposedHelpers.getObjectField(param.thisObject, "tileViewFactory"); View btTileView = mView.findViewWithTag("big_tile_bt"); int btTileId = ResourcesHook.getFakeResId("bt_big_tile"); btTileView.setId(btTileId); Object btController = XposedHelpers.callMethod(factory, "create", btTileView, "bt"); XposedHelpers.setAdditionalInstanceField(param.thisObject, "btTileView", btTileView); XposedHelpers.setAdditionalInstanceField(param.thisObject, "btController", btController); Class mConstraintSetClass = pluginLoader.loadClass("androidx.constraintlayout.widget.ConstraintSet"); Object constraintSet = XposedHelpers.newInstance(mConstraintSetClass); XposedHelpers.callMethod(constraintSet, "clone", mView); View bigTileA = (View) XposedHelpers.getObjectField(param.thisObject, "bigTileA"); if (styleId == 2) { XposedHelpers.callMethod(constraintSet, "connect", bigTileB.getId(), 7, btTileId, 6); XposedHelpers.callMethod(constraintSet, "connect", btTileId, 6, bigTileB.getId(), 7); XposedHelpers.callMethod(constraintSet, "connect", btTileId, 7, bigTileA.getId(), 7); XposedHelpers.callMethod(constraintSet, "connect", btTileId, 3, bigTileB.getId(), 3); XposedHelpers.callMethod(constraintSet, "connect", btTileId, 4, 0, 4); XposedHelpers.callMethod(constraintSet, "setMargin", btTileId, 6, (int) dp2px2(10)); int labelResId = mView.getResources().getIdentifier("label_container", "id", "miui.systemui.plugin"); bigTileB.findViewById(labelResId).setVisibility(View.GONE); btTileView.findViewById(labelResId).setVisibility(View.GONE); int iconResId = mView.getResources().getIdentifier("status_icon", "id", "miui.systemui.plugin"); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) bigTileB.findViewById(iconResId).getLayoutParams(); layoutParams.leftMargin = (int) dp2px2(3); layoutParams = (LinearLayout.LayoutParams) btTileView.findViewById(iconResId).getLayoutParams(); layoutParams.leftMargin = (int) dp2px2(3); } else { XposedHelpers.callMethod(constraintSet, "connect", bigTileB.getId(), 4, btTileId, 3); XposedHelpers.callMethod(constraintSet, "connect", btTileId, 6, bigTileA.getId(), 6); XposedHelpers.callMethod(constraintSet, "connect", btTileId, 7, bigTileA.getId(), 7); XposedHelpers.callMethod(constraintSet, "connect", btTileId, 3, bigTileB.getId(), 4); XposedHelpers.callMethod(constraintSet, "connect", btTileId, 4, 0, 4); } XposedHelpers.callMethod(constraintSet, "constrainWidth", btTileId, 0); XposedHelpers.callMethod(constraintSet, "constrainHeight", btTileId, 0); XposedHelpers.callMethod(constraintSet, "applyTo", mView); } if (styleId == 3) { ViewGroup.LayoutParams layoutParams = bigTileB.getLayoutParams(); int verticalMargin = (int) dp2px2(4); ((ViewGroup.MarginLayoutParams) layoutParams).topMargin = verticalMargin; ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = verticalMargin; } } }; Helpers.findAndHookMethod("miui.systemui.controlcenter.qs.tileview.BigTileGroupController", pluginLoader, "updateResources", updateStyleHook); Helpers.findAndHookMethod("miui.systemui.controlcenter.qs.tileview.BigTileGroupController", pluginLoader, "setListening", boolean.class, new MethodHook() { @Override protected void after(XC_MethodHook.MethodHookParam param) { Object btController = XposedHelpers.getAdditionalInstanceField(param.thisObject, "btController"); if (btController != null) { XposedHelpers.callMethod(btController, "setListening", param.args[0]); } } }); Helpers.findAndHookMethod("miui.systemui.controlcenter.qs.tileview.BigTileGroupController", pluginLoader, "getRowViews", int.class, new MethodHook() { @Override protected void after(XC_MethodHook.MethodHookParam param) { int row = (int) param.args[0]; Object btTileView; if (row == 1 && (btTileView = XposedHelpers.getAdditionalInstanceField(param.thisObject, "btTileView")) != null) { ((ArrayList)param.getResult()).add(btTileView); } } }); Helpers.findAndHookMethod("miui.systemui.controlcenter.qs.tileview.BigTileGroupController", pluginLoader, "getChildControllers", new MethodHook() { @Override protected void after(XC_MethodHook.MethodHookParam param) { Object btController = XposedHelpers.getAdditionalInstanceField(param.thisObject, "btController"); if (btController != null) { ((ArrayList)param.getResult()).add(btController); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/CCGrid.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.annotation.SuppressLint import android.content.Context import android.content.pm.ApplicationInfo import android.text.TextUtils import android.util.AttributeSet import android.view.View import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.R import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidT import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidU import de.robv.android.xposed.XposedHelpers object CCGrid : BaseHook() { private val cols by lazy { mPrefsMap.getInt("system_control_center_cc_columns", 4) } private val rows by lazy { mPrefsMap.getInt("system_control_center_cc_rows", 4) } private val label by lazy { mPrefsMap.getBoolean("system_control_center_qs_tile_label") } private var scaledTileWidthDim = -1f @SuppressLint("DiscouragedApi") override fun init() { if (cols > 4) { mResHook.setObjectReplacement( lpparam.packageName, "dimen", "qs_control_tiles_columns", cols ) } Helpers.findAndHookMethod( "com.android.systemui.SystemUIApplication", lpparam.classLoader, "onCreate", object : MethodHook() { private var isHooked = false override fun after(param: MethodHookParam) { if (!isHooked) { isHooked = true val mContext = XposedHelpers.callMethod( param.thisObject, "getApplicationContext" ) as Context val res = mContext.resources val density = res.displayMetrics.density val tileWidthResId = res.getIdentifier( "qs_control_center_tile_width", "dimen", "com.android.systemui" ) var tileWidthDim = res.getDimension(tileWidthResId) if (cols > 4) { tileWidthDim /= density scaledTileWidthDim = tileWidthDim * 4 / cols mResHook.setDensityReplacement( lpparam.packageName, "dimen", "qs_control_center_tile_width", scaledTileWidthDim ) mResHook.setDensityReplacement( "miui.systemui.plugin", "dimen", "qs_control_center_tile_width", scaledTileWidthDim ) mResHook.setDensityReplacement( lpparam.packageName, "dimen", "qs_control_tile_icon_bg_size", scaledTileWidthDim ) mResHook.setDensityReplacement( "miui.systemui.plugin", "dimen", "qs_control_tile_icon_bg_size", scaledTileWidthDim ) mResHook.setDensityReplacement( "miui.systemui.plugin", "dimen", "qs_cell_height", 85f ) } } } }) val pluginLoaderClass = if (isAndroidU()) "com.android.systemui.shared.plugins.PluginInstance\$Factory\$\$ExternalSyntheticLambda0" else if (isAndroidT()) "com.android.systemui.shared.plugins.PluginInstance\$Factory" else "com.android.systemui.shared.plugins.PluginManagerImpl" var appInfo: ApplicationInfo? if (isAndroidU()) { hookAllMethods("com.android.systemui.shared.plugins.PluginInstance\$Factory", "create", object : MethodHook() { override fun before(param: MethodHookParam) { appInfo = param.args[1] as ApplicationInfo ClassUtils.loadClass(pluginLoaderClass, lpparam.classLoader).methodFinder().first { name == "get" }.createHook { after { getClassLoader -> if (appInfo!!.packageName == "miui.systemui.plugin") { val classLoader = getClassLoader.result as ClassLoader loadCCGrid(classLoader) } } } } } ) } else { ClassUtils.loadClass(pluginLoaderClass, lpparam.classLoader).methodFinder().first { name == "getClassLoader" }.createHook { after { getClassLoader -> appInfo = getClassLoader.args[0] as ApplicationInfo if (appInfo!!.packageName == "miui.systemui.plugin") { val classLoader = getClassLoader.result as ClassLoader loadCCGrid(classLoader) } } } } } private fun loadCCGrid(pluginLoader: ClassLoader) { if (cols > 4) { Helpers.findAndHookConstructor("miui.systemui.controlcenter.qs.QSPager", pluginLoader, Context::class.java, AttributeSet::class.java, object : MethodHook() { override fun after(param: MethodHookParam) { XposedHelpers.setObjectField( param.thisObject, "columns", cols ) } }) if (!label) { Helpers.findAndHookMethod("miui.systemui.controlcenter.qs.tileview.StandardTileView", pluginLoader, "createLabel", Boolean::class.javaPrimitiveType, object : MethodHook() { override fun after(param: MethodHookParam) { val label = XposedHelpers.getObjectField( param.thisObject, "label" ) if (label != null) { val lb = label as TextView lb.maxLines = 1 lb.isSingleLine = true lb.ellipsize = TextUtils.TruncateAt.MARQUEE lb.marqueeRepeatLimit = 0 val labelContainer = XposedHelpers.getObjectField( param.thisObject, "labelContainer" ) as View labelContainer.setPadding(4, 0, 4, 0) } } }) } } if (rows != 4) { Helpers.findAndHookMethod( "miui.systemui.controlcenter.qs.QSPager", pluginLoader, "distributeTiles", object : MethodHook() { override fun after(param: MethodHookParam) { val collapse = XposedHelpers.getObjectField( param.thisObject, "collapse" ) as Boolean if (collapse) { val pages = XposedHelpers.getObjectField( param.thisObject, "pages" ) as ArrayList<*> for (tileLayoutImpl in pages) { XposedHelpers.callMethod( tileLayoutImpl, "removeTiles" ) } val pageTiles = ArrayList() var currentRow = 2 val records = XposedHelpers.getObjectField( param.thisObject, "records" ) as ArrayList<*> val it2: Iterator<*> = records.iterator() var i3 = 0 var pageNow = 0 val bigHeader = XposedHelpers.getObjectField( param.thisObject, "header" ) while (it2.hasNext()) { val tileRecord = it2.next()!! pageTiles.add(tileRecord) i3++ if (i3 >= cols) { currentRow++ i3 = 0 } if (currentRow >= rows || !it2.hasNext()) { XposedHelpers.callMethod( pages[pageNow], "setTiles", pageTiles, if (pageNow == 0) bigHeader else null ) pageTiles.clear() val totalRows = XposedHelpers.getObjectField( param.thisObject, "rows" ) as Int if (currentRow > totalRows) { XposedHelpers.setObjectField( param.thisObject, "rows", currentRow ) } if (it2.hasNext()) { pageNow++ currentRow = 0 } } } val it3 = pages.iterator() while (it3.hasNext()) { val next2 = it3.next() val isEmpty = XposedHelpers.callMethod( next2, "isEmpty" ) as Boolean if (isEmpty) { it3.remove() } } val pageIndicator = XposedHelpers.getObjectField( param.thisObject, "pageIndicator" ) if (pageIndicator != null) { XposedHelpers.callMethod( pageIndicator, "setNumPages", pages.size ) } val adapter = XposedHelpers.getObjectField( param.thisObject, "adapter" ) XposedHelpers.callMethod( param.thisObject, "setAdapter", adapter ) // XposedHelpers.callMethod(param.thisObject, "notifyDataSetChanged"); } } }) } // 移除磁贴标题相关 if (mPrefsMap.getBoolean("system_control_center_qs_tile_label")) { mHideCCLabels(pluginLoader) } // 新控制中心矩形圆角 if (mPrefsMap.getBoolean("system_ui_control_center_rounded_rect")) { mResHook.setResReplacement( "miui.systemui.plugin", "drawable", "qs_background_unavailable", R.drawable.ic_qs_tile_bg_disabled ) mResHook.setResReplacement( "miui.systemui.plugin", "drawable", "qs_background_disabled", R.drawable.ic_qs_tile_bg_disabled ) mResHook.setResReplacement( "miui.systemui.plugin", "drawable", "qs_background_warning", R.drawable.ic_qs_tile_bg_warning ) mCCTileCornerHook(pluginLoader) } } private fun mHideCCLabels(pluginLoader: ClassLoader?) { mResHook.setDensityReplacement( "miui.systemui.plugin", "dimen", "qs_cell_height", 85f ) val mQSController = XposedHelpers.findClassIfExists( "miui.systemui.controlcenter.qs.tileview.StandardTileView", pluginLoader ) Helpers.hookAllMethods(mQSController, "init", object : MethodHook() { override fun before(param: MethodHookParam) { if (param.args.size != 1) return val mLabelContainer = XposedHelpers.getObjectField( param.thisObject, "labelContainer" ) as View if (mLabelContainer != null) { mLabelContainer.visibility = View.GONE } } }) } private fun mCCTileCornerHook(pluginLoader: ClassLoader?) { Helpers.findAndHookMethod("miui.systemui.controlcenter.qs.tileview.ExpandableIconView", pluginLoader, "setCornerRadius", Float::class.javaPrimitiveType, object : MethodHook() { override fun before(param: MethodHookParam) { val mContext = XposedHelpers.callMethod( param.thisObject, "getPluginContext" ) as Context var radius = 18f if (scaledTileWidthDim > 0) { radius *= scaledTileWidthDim / 65 } param.args[0] = mContext.resources.displayMetrics.density * radius } }) Helpers.findAndHookMethod("miui.systemui.dagger.PluginComponentFactory", pluginLoader, "create", Context::class.java, object : MethodHook() { override fun before(param: MethodHookParam) { val mContext = param.args[0] as Context val res = mContext.resources val enabledTileBackgroundResId = res.getIdentifier( "qs_background_enabled", "drawable", "miui.systemui.plugin" ) val enabledTileColorResId = res.getIdentifier( "qs_enabled_color", "color", "miui.systemui.plugin" ) val tintColor = res.getColor(enabledTileColorResId, null) val imgHook: MethodHook = object : MethodHook() { override fun before(param: MethodHookParam) { val resId = param.args[0] as Int if (resId == enabledTileBackgroundResId && resId != 0) { val enableTile = Helpers.getModuleRes(mContext) .getDrawable(R.drawable.ic_qs_tile_bg_enabled, null) enableTile.setTint(tintColor) param.result = enableTile } } } Helpers.findAndHookMethod( "android.content.res.Resources", pluginLoader, "getDrawable", Int::class.javaPrimitiveType, imgHook ) Helpers.findAndHookMethod( "android.content.res.Resources.Theme", pluginLoader, "getDrawable", Int::class.javaPrimitiveType, imgHook ) } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/CompactNotificationsHook.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.annotation.SuppressLint import android.view.View import android.view.ViewGroup import android.view.ViewGroup.MarginLayoutParams import android.widget.FrameLayout import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers import de.robv.android.xposed.XposedHelpers import kotlin.math.roundToInt object CompactNotificationsHook : BaseHook() { @SuppressLint("DiscouragedApi") override fun init() { val abHeight = 39.0f if (mPrefsMap.getBoolean("system_ui_control_center_compact_notice")) { mResHook.setDensityReplacement("android", "dimen", "notification_action_height", abHeight) mResHook.setDensityReplacement("android", "dimen", "android_notification_action_height", abHeight) mResHook.setDensityReplacement("android", "dimen", "notification_action_list_height", abHeight) mResHook.setDensityReplacement("com.android.systemui", "dimen", "notification_row_extra_padding", 0F) } Helpers.hookAllMethods( "com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper", lpparam.classLoader, "wrap", object : MethodHook() { @Throws(Throwable::class) override fun after(param: MethodHookParam) { if (param.args.size > 3) return val res = param.result ?: return val mView = XposedHelpers.getObjectField(res, "mView") as View // if (mView.getId() != mView.getResources().getIdentifier("status_bar_latest_event_content", "id", "android")) return; val container = mView.findViewById( mView.resources.getIdentifier("actions_container", "id", "android") ) ?: return val density = mView.resources.displayMetrics.density val height = (density * abHeight).roundToInt() val actions = container.getChildAt(0) as ViewGroup val lp1 = actions.layoutParams as FrameLayout.LayoutParams lp1.height = height actions.layoutParams = lp1 actions.setPadding(0, 0, 0, 0) for (c in 0 until actions.childCount) { val button = actions.getChildAt(c) val lp2 = button.layoutParams as MarginLayoutParams lp2.height = height lp2.bottomMargin = 0 lp2.topMargin = 0 } } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/ControlCenterStyle.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.ObjectUtils.setObject import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object ControlCenterStyle : BaseHook() { override fun init() { loadClass("com.android.systemui.controlcenter.policy.ControlCenterControllerImpl").declaredConstructors.createHooks { after { setObject(it.thisObject, "forceUseControlCenterPanel", false) } } loadClass("com.miui.systemui.SettingsObserver").methodFinder() .filterByName("setValue\$default").first() .createHook { before { if (it.args[1] == "force_use_control_panel") { it.args[2] = 0 } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/FiveGTile.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; import android.os.Build; import android.os.Handler; import android.provider.Settings; import android.util.ArrayMap; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.utils.TileUtils; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.XposedHelpers; import miui.telephony.TelephonyManager; public class FiveGTile extends TileUtils { String mNfcTileClsName = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "com.android.systemui.qs.tiles.MiuiNfcTile" : "com.android.systemui.qs.tiles.NfcTile"; String mQSFactoryClsName = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "com.android.systemui.qs.tileimpl.MiuiQSFactory" : "com.android.systemui.qs.tileimpl.QSFactoryImpl"; @Override public void init() { super.init(); } @Override public Class customQSFactory() { return findClassIfExists(mQSFactoryClsName); } @Override public Class customClass() { return findClassIfExists(mNfcTileClsName); } @Override public String[] customTileProvider() { String[] TileProvider = new String[3]; TileProvider[0] = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "nfcTileProvider" : "mNfcTileProvider"; TileProvider[1] = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "createTileInternal" : "interceptCreateTile"; TileProvider[2] = "createTile"; return TileProvider; } @Override public String customName() { return "custom_5G"; } @Override public int customValue() { return R.string.system_control_center_5g_toggle_label; } @Override public boolean needCustom() { return true; } @Override public boolean needAfter() { return false; } @Override public void tileCheck(MethodHookParam param, String tileName) { // 获取设置是否支持5G param.setResult(TelephonyManager.getDefault().isFiveGCapable()); } @Override public void tileLongClickIntent(MethodHookParam param, String tileName) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); intent.setComponent(new ComponentName("com.android.phone", "com.android.phone.settings.MiuiFiveGNetworkSetting")); // 原活动是 com.android.phone.settings.PreferredNetworkTypeListPreference param.setResult(intent); } @Override public void tileClick(MethodHookParam param, String tileName) { TelephonyManager manager = TelephonyManager.getDefault(); // 切换5G状态 manager.setUserFiveGEnabled(!manager.isUserFiveGEnabled()); // 更新磁贴状态 XposedHelpers.callMethod(param.thisObject, "refreshState"); } @Override public void tileListening(MethodHookParam param, String tileName) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); boolean mListening = (boolean) param.args[0]; if (mListening) { ContentObserver contentObserver = new ContentObserver(new Handler(mContext.getMainLooper())) { @Override public void onChange(boolean z) { XposedHelpers.callMethod(param.thisObject, "refreshState"); } }; mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor("fiveg_user_enable"), false, contentObserver); mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor("dual_nr_enabled"), false, contentObserver); XposedHelpers.setAdditionalInstanceField(param.thisObject, "tileListener", contentObserver); } else { ContentObserver contentObserver = (ContentObserver) XposedHelpers.getAdditionalInstanceField(param.thisObject, "tileListener"); mContext.getContentResolver().unregisterContentObserver(contentObserver); } } @Override public ArrayMap tileUpdateState(MethodHookParam param, Class mResourceIcon, String tileName) { boolean isEnable; TelephonyManager manager = TelephonyManager.getDefault(); isEnable = manager.isUserFiveGEnabled(); ArrayMap tileResMap = new ArrayMap<>(); tileResMap.put("custom_5G_Enable", isEnable ? 1 : 0); tileResMap.put("custom_5G_ON", mResHook.addResource("ic_control_center_5g_toggle_on", R.drawable.ic_control_center_5g_toggle_on)); tileResMap.put("custom_5G_OFF", mResHook.addResource("ic_control_center_5g_toggle_off", R.drawable.ic_control_center_5g_toggle_off)); return tileResMap; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/FixMediaControlPanel.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import com.github.kyuubiran.ezxhelper.EzXHelper import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import com.sevtinge.cemiuiler.utils.setObjectField import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers object FixMediaControlPanel : BaseHook() { override fun init() { try { EzXHelper.initHandleLoadPackage(lpparam) XposedHelpers.findAndHookMethod("com.android.systemui.statusbar.notification.mediacontrol.MiuiMediaControlPanel", lpparam.classLoader, "setArtwork", XposedHelpers.findClass("com.android.systemui.media.MediaData", lpparam.classLoader), object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { param.thisObject.setObjectField("mCurrentKey", "") } }) } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/FlashLight.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidU; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.content.Context; import android.database.ContentObserver; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.provider.Settings; import android.util.ArrayMap; import androidx.annotation.Nullable; import com.sevtinge.cemiuiler.utils.MathUtils; import com.sevtinge.cemiuiler.utils.ShellUtils; import com.sevtinge.cemiuiler.utils.TileUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; public class FlashLight extends TileUtils { String mQSFactoryClsName = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "com.android.systemui.qs.tileimpl.MiuiQSFactory" : "com.android.systemui.qs.tileimpl.QSFactoryImpl"; public final String flashFileMtk = "/sys/class/flashlight_core/flashlight/torchbrightness"; public final String flashFileTorch = "/sys/class/leds/led:torch_0/brightness"; public final String flashFileOther = "/sys/class/leds/flashlight/brightness"; public final String flashFileSwitch = "/sys/class/leds/led:switch_0/brightness"; public final String maxFile = "/sys/class/leds/led:torch_0/max_brightness"; public boolean isListening = false; public boolean suGet; @Override public void init() { super.init(); } @Override public Class customQSFactory() { return findClassIfExists(mQSFactoryClsName); } @Override public Class customClass() { return findClassIfExists("com.android.systemui.qs.tiles.MiuiFlashlightTile"); } @Override public String[] customTileProvider() { String[] TileProvider = new String[3]; TileProvider[0] = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "flashlightTileProvider" : "mFlashlightTileProvider"; TileProvider[1] = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "createTileInternal" : "interceptCreateTile"; TileProvider[2] = "createTile"; return TileProvider; } @Override public boolean needCustom() { return false; } @Override public boolean needAfter() { return true; } @Override public void tileClickAfter(XC_MethodHook.MethodHookParam param, String tileName) { } @Override public ArrayMap tileUpdateState(XC_MethodHook.MethodHookParam param, Class mResourceIcon, String tileName) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); ContentObserver contentObserver; // XposedLogUtils.logE(TAG, "tileUpdateState: args: " + param.args[1]); if (param.args[1] != null) { boolean enabled = (boolean) param.args[1]; Object flash = XposedHelpers.getObjectField(param.thisObject, "flashlightController"); if (enabled) { if (getFlashLightEnabled(mContext) == 1 && !isListening) { setFlashLightEnabled(mContext, 0); } if (!isListening) listening(mContext, param, flash, isListening); setFlashLightEnabled(mContext, 1); // XposedLogUtils.logE(TAG, "tileUpdateState: isListening1: " + isListening); } else if ((boolean) XposedHelpers.callMethod(flash, "isEnabled")) { if (getFlashLightEnabled(mContext) == 1 && !isListening) { setFlashLightEnabled(mContext, 0); } if (!isListening) listening(mContext, param, flash, isListening); setFlashLightEnabled(mContext, 1); // XposedLogUtils.logE(TAG, "tileUpdateState: isListening2: " + isListening + " call: " + XposedHelpers.callMethod(flash, "isEnabled")); } else { setFlashLightEnabled(mContext, 0); if (isListening) { listening(mContext, param, flash, isListening); contentObserver = (ContentObserver) XposedHelpers.getAdditionalInstanceField(param.thisObject, "tileListener"); if (contentObserver != null) { mContext.getContentResolver().unregisterContentObserver(contentObserver); } } // XposedLogUtils.logE(TAG, "tileUpdateState: isListening3: " + isListening); } } return null; } public void listening(Context mContext, XC_MethodHook.MethodHookParam param, Object flash, boolean isListening) { if (!isListening) { ContentObserver contentObserver = new ContentObserver(new Handler(mContext.getMainLooper())) { @Override public void onChange(boolean selfChange, @Nullable Uri uri) { super.onChange(selfChange, uri); hookFlash(param.thisObject, flash, mContext, readFile()); // XposedLogUtils.logE(TAG, "listening: listening: selfChange: " + selfChange + " uri: " + uri); } }; mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor("flash_light_enabled"), false, contentObserver); XposedHelpers.setAdditionalInstanceField(param.thisObject, "tileListener", contentObserver); this.isListening = true; } else this.isListening = false; } public void hookFlash(Object o, Object flash, Context context, int max) { if (!isAndroidU()) { setBrightnessUtils(o, flash, context, max); findAndHookMethod("com.android.systemui.controlcenter.policy.MiuiBrightnessController", "lambda$onChanged$0", boolean.class, float.class, new MethodHook() { @Override protected void before(MethodHookParam param) { // XposedLogUtils.logE(TAG, "MiuiBrightnessController lambda$onChanged$0: " + param.args[0] + " 2: " + param.args[1]); Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); int enabled = getFlashLightEnabled(mContext); // XposedLogUtils.logE(TAG, "lambda$onChanged$0 enabled: " + enabled); if (enabled == 1) { param.setResult(null); } } } ); findAndHookMethod("com.android.systemui.controlcenter.policy.MiuiBrightnessController$5", "run", new MethodHook() { @Override protected void before(MethodHookParam param) { int enabled = getFlashLightEnabled(context); // XposedLogUtils.logE(TAG, "MiuiBrightnessController$5 enabled: " + enabled); if (enabled == 1) { // XposedLogUtils.logE(TAG, "MiuiBrightnessController$5 run"); param.setResult(null); } } } ); } else { setBrightnessUtils(o, flash, context, max); findAndHookMethod("com.android.systemui.controlcenter.policy.MiuiBrightnessController$$ExternalSyntheticLambda0", "run", new MethodHook() { @Override protected void before(MethodHookParam param) { if (getFlashLightEnabled(context) == 1) { // XposedLogUtils.logE(TAG, "MiuiBrightnessController$$ExternalSyntheticLambda0 run"); param.setResult(null); } } } ); findAndHookMethod("com.android.systemui.controlcenter.policy.MiuiBrightnessController$2", "run", new MethodHook() { @Override protected void before(MethodHookParam param) { if (getFlashLightEnabled(context) == 1) { // XposedLogUtils.logE(TAG, "MiuiBrightnessController$2 run"); param.setResult(null); } } } ); } } public void setBrightnessUtils(Object o, Object flash, Context context, int maxPath) { findAndHookMethod("com.android.systemui.controlcenter.policy.BrightnessUtils", "convertGammaToLinearFloat", int.class, float.class, float.class, new MethodHook() { @Override protected void before(MethodHookParam param) { if (getFlashLightEnabled(context) == 1) { // AndroidLogUtils.deLogI("FlashLight", "convertGammaToLinearFloat int 1: " + param.args[0]); // AndroidLogUtils.deLogI("FlashLight", "convertGammaToLinearFloat float 2: " + param.args[1]); // AndroidLogUtils.deLogI("FlashLight", "convertGammaToLinearFloat float 3: " + param.args[2]); // XposedLogUtils.logE(TAG, "convertGammaToLinearFloat int 1: " + param.args[0]); // XposedLogUtils.logE(TAG, "convertGammaToLinearFloat float 2: " + param.args[1]); // XposedLogUtils.logE(TAG, "convertGammaToLinearFloat float 3: " + param.args[2]); float min = (float) param.args[1]; float max = (float) param.args[2]; if (min < 0.001f) { min = 0.00114514f; } min = Math.round(min * 500); max = Math.round(max * 500); float exp; Class BrightnessUtils = XposedHelpers.findClass("com.android.systemui.controlcenter.policy.BrightnessUtils", lpparam.classLoader); int GAMMA_SPACE_MAX = XposedHelpers.getStaticIntField(BrightnessUtils, "GAMMA_SPACE_MAX"); float R = XposedHelpers.getStaticFloatField(BrightnessUtils, "R"); float A = XposedHelpers.getStaticFloatField(BrightnessUtils, "A"); float B = XposedHelpers.getStaticFloatField(BrightnessUtils, "B"); float C = XposedHelpers.getStaticFloatField(BrightnessUtils, "C"); float norm = MathUtils.norm(0.0f, GAMMA_SPACE_MAX, (int) param.args[0]); if (norm <= R) { exp = MathUtils.sq(norm / R); } else { exp = MathUtils.exp((norm - C) / A) + B; } if (min < 10) { min = 12; } // AndroidLogUtils.deLogI("FlashLight", "convertGammaToLinearFloat R: " + R + " A: " + A + " B: " + B + " C: " + C); // AndroidLogUtils.deLogI("FlashLight", "convertGammaToLinearFloat exp: " + exp); float end = MathUtils.lerpNew(min, max, (MathUtils.constrain(exp, 0.0f, 12.0f) / 12.0f)); // AndroidLogUtils.deLogI("FlashLight", "convertGammaToLinearFloat min: " + min); // AndroidLogUtils.deLogI("FlashLight", "convertGammaToLinearFloat max: " + max); // AndroidLogUtils.deLogI("FlashLight", "convertGammaToLinearFloat end: " + end); int i = Math.round(end); if (i != 0) { if (maxPath != -1 && i > maxPath) { i = maxPath; } // XposedLogUtils.logE(TAG, "convertGammaToLinearFloat i: " + i); writeFile(i); } else { XposedHelpers.callMethod(flash, "setFlashlight", false); XposedHelpers.callMethod(o, "refreshState"); } param.setResult(end); } } } ); } public int getFlashLightEnabled(Context context) { try { return Settings.System.getInt(context.getContentResolver(), "flash_light_enabled"); } catch (Settings.SettingNotFoundException e) { XposedLogUtils.logE(TAG, "No Found flash_light_enabled: " + e); return -1; } } public void setFlashLightEnabled(Context context, int set) { Settings.System.putInt(context.getContentResolver(), "flash_light_enabled", set); } public int readFile() { String line; BufferedReader reader = null; StringBuilder builder = null; File file = new File(maxFile); if (file.exists()) { try { reader = new BufferedReader(new FileReader(maxFile)); builder = new StringBuilder(); while ((line = reader.readLine()) != null) { builder.append(line); } } catch (IOException e) { XposedLogUtils.logE(TAG, "Error to read: " + maxFile, e); } finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { XposedLogUtils.logE(TAG, "Close reader error: ", e); } } } else { XposedLogUtils.logE(TAG, "Not Found FlashLight File: " + maxFile); } if (builder != null) { return Integer.parseInt(builder.toString()); } return -1; } public void writeFile(int flashInt) { File file = new File(flashFileMtk); if (file.exists()) { writeFileModule(flashFileMtk, flashInt); } else { File file1 = new File(flashFileTorch); File file2 = new File(flashFileSwitch); File file3 = new File(flashFileOther); if (file1.exists()) { writeFileModule(flashFileTorch, flashInt); if (file3.exists()) { writeFileModule(flashFileOther, flashInt); } } else XposedLogUtils.logE(TAG, "Not Found FlashLight File: " + flashFileMtk + " And: " + flashFileTorch); // if (file1.exists() && file2.exists()) { // writeFileModule(flashFileTorch, flashInt); // writeFileModule(flashFileSwitch, 1); // writeFileModule(flashFileSwitch, 0); // } else if (file1.exists()) { // writeFileModule(flashFileTorch, flashInt); // } else // XposedLogUtils.logE(TAG, "Not Found FlashLight File: " + flashFileMtk + " And: " + flashFileTorch); } } public void writeFileModule(String filePath, int flashInt) { try (FileWriter writer = new FileWriter(filePath, false)) { writer.write(Integer.toString(flashInt)); writer.flush(); } catch (IOException e) { if (!suGet) { ShellUtils.execCommand("chmod 777 " + filePath, true, false); suGet = true; } try (FileWriter writer = new FileWriter(filePath, false)) { writer.write(Integer.toString(flashInt)); writer.flush(); } catch (IOException f) { XposedLogUtils.logE(TAG, "Write FlashLight File Error: " + f + " File Path: " + filePath); } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/GmsTile.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Build; import android.util.ArrayMap; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.utils.TileUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.XposedHelpers; public class GmsTile extends TileUtils { public final String CheckGms = "com.google.android.gms"; public final String mQSFactoryClsName = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "com.android.systemui.qs.tileimpl.MiuiQSFactory" : "com.android.systemui.qs.tileimpl.QSFactoryInjectorImpl"; public final String[] GmsAppsSystem = new String[]{ "com.google.android.gms", "com.google.android.gsf", "com.android.vending", "com.google.android.syncadapters.contacts", "com.google.android.backuptransport", "com.google.android.onetimeinitializer", "com.google.android.partnersetup", "com.google.android.configupdater", "com.google.android.ext.shared", "com.google.android.printservice.recommendation"}; @Override public void init() { super.init(); } @Override public Class customQSFactory() { return findClassIfExists(mQSFactoryClsName); } @Override public Class customClass() { return findClassIfExists("com.android.systemui.qs.tiles.ScreenLockTile"); } @Override public String[] customTileProvider() { String[] TileProvider = new String[3]; TileProvider[0] = "screenLockTileProvider"; TileProvider[1] = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "createTileInternal" : "interceptCreateTile"; TileProvider[2] = "createTile"; return TileProvider; } @Override public boolean needCustom() { return true; } @Override public String customName() { return "custom_GMS"; } @Override public int customValue() { return R.string.security_center_gms_open; } @Override public boolean needAfter() { return false; } @Override public void tileCheck(MethodHookParam param, String tileName) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); PackageManager packageManager = mContext.getPackageManager(); try { packageManager.getPackageInfo(CheckGms, PackageManager.GET_ACTIVITIES); param.setResult(true); } catch (PackageManager.NameNotFoundException e) { XposedLogUtils.logE(TAG, "Not Find GMS App: " + e); param.setResult(false); } } @Override public Intent tileHandleLongClick(MethodHookParam param, String tileName) { // 长按跳转谷歌基础服务页面 Intent intent = new Intent(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.googlebase.ui.GmsCoreSettings")); return intent; } @Override public void tileClick(MethodHookParam param, String tileName) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); PackageManager packageManager = mContext.getPackageManager(); int End = packageManager.getApplicationEnabledSetting(CheckGms); if (End == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) { for (String GmsAppsSystem : GmsAppsSystem) { try { packageManager.getPackageInfo(GmsAppsSystem, PackageManager.GET_ACTIVITIES); packageManager.setApplicationEnabledSetting(GmsAppsSystem, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); XposedLogUtils.logI("To Enabled Gms App:" + GmsAppsSystem); } catch (PackageManager.NameNotFoundException e) { XposedLogUtils.logI("Don't have Gms app :" + GmsAppsSystem); } } XposedHelpers.callMethod(param.thisObject, "refreshState"); } else if (End == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || End == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { for (String GmsAppsSystem : GmsAppsSystem) { try { packageManager.getPackageInfo(GmsAppsSystem, PackageManager.GET_ACTIVITIES); packageManager.setApplicationEnabledSetting(GmsAppsSystem, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0); XposedLogUtils.logI("To Disabled Gms App:" + GmsAppsSystem); } catch (PackageManager.NameNotFoundException e) { XposedLogUtils.logI("Don't have Gms app :" + GmsAppsSystem); } } XposedHelpers.callMethod(param.thisObject, "refreshState"); } } @Override public ArrayMap tileUpdateState(MethodHookParam param, Class mResourceIcon, String tileName) { boolean isEnable; Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); PackageManager packageManager = mContext.getPackageManager(); int End = packageManager.getApplicationEnabledSetting(CheckGms); isEnable = End == PackageManager.COMPONENT_ENABLED_STATE_ENABLED; ArrayMap tileResMap = new ArrayMap<>(); tileResMap.put("custom_GMS_Enable", isEnable ? 1 : 0); tileResMap.put("custom_GMS_ON", mResHook.addResource("ic_control_center_gms_toggle_on", R.drawable.ic_control_center_gms_toggle_on)); tileResMap.put("custom_GMS_OFF", mResHook.addResource("ic_control_center_gms_toggle_off", R.drawable.ic_control_center_gms_toggle_off)); return tileResMap; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/MuteVisibleNotifications.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import android.content.Context; import android.os.PowerManager; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import de.robv.android.xposed.XposedHelpers; public class MuteVisibleNotifications extends BaseHook { @Override public void init() { Helpers.hookAllMethods("com.android.systemui.statusbar.notification.policy.NotificationAlertController", lpparam.classLoader, "buzzBeepBlink", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); PowerManager powerMgr = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); if (powerMgr.isInteractive()) { param.setResult(null); } } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/NotificationWeather.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.annotation.SuppressLint import android.content.ComponentName import android.content.Intent import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView import android.widget.Toast import androidx.constraintlayout.widget.ConstraintLayout import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DisplayUtils import com.sevtinge.cemiuiler.utils.DisplayUtils.dip2px import com.sevtinge.cemiuiler.utils.SystemProperties import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.setObjectField import com.sevtinge.cemiuiler.view.WeatherView object NotificationWeather : BaseHook() { @SuppressLint("DiscouragedApi") override fun init() { var mWeatherView: TextView? = null var mConstraintLayout: ConstraintLayout? = null val isDisplayCity = mPrefsMap.getBoolean("system_ui_control_center_show_weather_city") loadClass("com.android.systemui.qs.MiuiNotificationHeaderView").methodFinder().first { name == "onFinishInflate" }.createHook { after { param -> val viewGroup = param.thisObject as ViewGroup val context = viewGroup.context // MIUI编译时间大于 2022-03-12 00:00:00 且为内测版 if (SystemProperties[context, "ro.build.date.utc"].toInt() >= 1647014400 && !SystemProperties[context, "ro.build.version.incremental"].endsWith("XM") ) { // 获取原组件 val bigTimeId = context.resources.getIdentifier("big_time", "id", context.packageName) val bigTime: TextView = viewGroup.findViewById(bigTimeId) val dateTimeId = context.resources.getIdentifier("date_time", "id", context.packageName) val dateTime: TextView = viewGroup.findViewById(dateTimeId) // 创建新布局 val mConstraintLayoutLp = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT ).also { it.topMargin = context.resources.getDimensionPixelSize( context.resources.getIdentifier( "qs_control_header_tiles_margin_top", "dimen", context.packageName ) ) } mConstraintLayout = ConstraintLayout(context).also { it.layoutParams = mConstraintLayoutLp } (bigTime.parent as ViewGroup).addView(mConstraintLayout, 0) // 从原布局中删除组件 (bigTime.parent as ViewGroup).removeView(bigTime) (dateTime.parent as ViewGroup).removeView(dateTime) // 添加组件至新布局 mConstraintLayout!!.addView(bigTime) mConstraintLayout!!.addView(dateTime) // 组件属性 val dateTimeLp = ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT ).also { it.startToEnd = bigTimeId it.bottomToBottom = 0 it.marginStart = context.resources.getDimensionPixelSize( context.resources.getIdentifier( "notification_panel_time_date_space", "dimen", context.packageName ) ) it.bottomMargin = dip2px(context, 5f) } dateTime.layoutParams = dateTimeLp // 创建天气组件 mWeatherView = WeatherView(context, isDisplayCity).apply { setTextAppearance( context.resources.getIdentifier( "TextAppearance.QSControl.Date", "style", context.packageName ) ) } mConstraintLayout!!.addView(mWeatherView) val mweatherviewLp = ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.WRAP_CONTENT ).also { it.startToEnd = bigTimeId it.bottomToTop = dateTimeId it.marginStart = context.resources.getDimensionPixelSize( context.resources.getIdentifier( "notification_panel_time_date_space", "dimen", context.packageName ) ) } (mWeatherView as WeatherView).layoutParams = mweatherviewLp } else { val layoutParam = loadClass("androidx.constraintlayout.widget.ConstraintLayout\$LayoutParams").getConstructor( Int::class.java, Int::class.java ).newInstance( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT ) as ViewGroup.MarginLayoutParams layoutParam.setObjectField( "bottomToTop", context.resources.getIdentifier("date_time", "id", context.packageName) ) layoutParam.setObjectField( "startToEnd", context.resources.getIdentifier("big_time", "id", context.packageName) ) layoutParam.marginStart = context.resources.getDimensionPixelSize( context.resources.getIdentifier( "notification_panel_time_date_space", "dimen", context.packageName ) ) mWeatherView = WeatherView(context, isDisplayCity).apply { setTextAppearance( context.resources.getIdentifier( "TextAppearance.QSControl.Date", "style", context.packageName ) ) layoutParams = layoutParam } viewGroup.addView(mWeatherView) } (mWeatherView as WeatherView).setOnClickListener { try { val intent = Intent().apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK component = ComponentName( "com.miui.weather2", "com.miui.weather2.ActivityWeatherMain" ) } context.startActivity(intent) } catch (e: Exception) { Toast.makeText(context, "启动失败", Toast.LENGTH_LONG).show() } } } } loadClass("com.android.systemui.qs.MiuiNotificationHeaderView").methodFinder().first { name == "updateLayout" }.createHook { after { val viewGroup = it.thisObject as ViewGroup val context = viewGroup.context val mOrientation = viewGroup.getObjectField("mOrientation") as Int // MIUI编译时间大于 2022-03-12 00:00:00 且为内测版 if (SystemProperties[context, "ro.build.date.utc"].toInt() >= 1647014400 && !SystemProperties[context, "ro.build.version.incremental"].endsWith( "DEV" ) && !SystemProperties[context, "ro.build.version.incremental"].endsWith("XM") ) { if (mOrientation == 1) { mConstraintLayout!!.visibility = View.VISIBLE } else { mConstraintLayout!!.visibility = View.GONE } } else { if (mOrientation == 1) { mWeatherView!!.visibility = View.VISIBLE } else { mWeatherView!!.visibility = View.GONE } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/NotificationWeatherNew.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.annotation.SuppressLint import android.content.pm.ApplicationInfo import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.invokeMethod import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidT import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidU import com.sevtinge.cemiuiler.utils.getObjectFieldOrNullAs import com.sevtinge.cemiuiler.view.WeatherData @SuppressLint("StaticFieldLeak") object NotificationWeatherNew : BaseHook() { lateinit var weather: WeatherData var clockId: Int = -2 @SuppressLint("DiscouragedApi", "ClickableViewAccessibility") override fun init() { val mControlCenterDateViewClass = loadClass("com.android.systemui.controlcenter.phone.widget.ControlCenterDateView") mControlCenterDateViewClass.methodFinder().findSuper().first { name == "onDetachedFromWindow" }.createHook { before { if ((it.thisObject as TextView).id == clockId && this@NotificationWeatherNew::weather.isInitialized) { weather.onDetachedFromWindow() } } } mControlCenterDateViewClass.methodFinder().findSuper().first { name == "setText" }.createHook { before { val time = it.args[0]?.toString() val view = it.thisObject as TextView if (view.id == clockId && time != null && this@NotificationWeatherNew::weather.isInitialized) { // val layout = view.layoutParams as ViewGroup.MarginLayoutParams // val y = view.height / 2 // layout.topMargin = -y it.args[0] = "${weather.weatherData}$time" } } } val pluginLoaderClass = if (isAndroidU()) "com.android.systemui.shared.plugins.PluginInstance\$Factory\$\$ExternalSyntheticLambda0" else if (isAndroidT()) "com.android.systemui.shared.plugins.PluginInstance\$Factory" else "com.android.systemui.shared.plugins.PluginManagerImpl" var appInfo: ApplicationInfo? if (isAndroidU()) { hookAllMethods("com.android.systemui.shared.plugins.PluginInstance\$Factory", "create", object : MethodHook() { override fun before(param: MethodHookParam) { appInfo = param.args[1] as ApplicationInfo loadClass(pluginLoaderClass, lpparam.classLoader).methodFinder().first { name == "get" }.createHook { after { getClassLoader -> if (appInfo!!.packageName == "miui.systemui.plugin") { val classLoader = getClassLoader.result as ClassLoader mainPanelHeader(classLoader) } } } } } ) } else { loadClass(pluginLoaderClass, lpparam.classLoader).methodFinder().first { name == "getClassLoader" }.createHook { after { getClassLoader -> appInfo = getClassLoader.args[0] as ApplicationInfo if (appInfo!!.packageName == "miui.systemui.plugin") { val classLoader = getClassLoader.result as ClassLoader mainPanelHeader(classLoader) } } } } } fun mainPanelHeader(pluginClassLoader: ClassLoader) { val isDisplayCity = mPrefsMap.getBoolean("system_ui_control_center_show_weather_city") loadClass( "miui.systemui.controlcenter.windowview.MainPanelHeaderController", pluginClassLoader ).methodFinder().first { name == "addClockViews" }.createHook { after { val dateView = it.thisObject.getObjectFieldOrNullAs("dateView")!! clockId = dateView.id weather = WeatherData(dateView.context, isDisplayCity) weather.callBacks = { dateView.invokeMethod("updateTime") } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/NotificationWeatherOld.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.annotation.SuppressLint import android.content.ComponentName import android.content.Intent import android.view.ViewGroup import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import com.sevtinge.cemiuiler.utils.setObjectField import com.sevtinge.cemiuiler.view.WeatherView object NotificationWeatherOld : BaseHook() { @SuppressLint("DiscouragedApi") override fun init() { var mWeatherView: TextView? val isDisplayCity = mPrefsMap.getBoolean("system_ui_control_center_show_weather_city") loadClass("com.android.systemui.qs.MiuiQSHeaderView").methodFinder().first { name == "onFinishInflate" }.createHook { after { val viewGroup = it.thisObject as ViewGroup val context = viewGroup.context val layoutParam = loadClass("androidx.constraintlayout.widget.ConstraintLayout\$LayoutParams") .getConstructor(Int::class.java, Int::class.java) .newInstance( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT ) as ViewGroup.MarginLayoutParams layoutParam.setObjectField( "endToStart", context.resources.getIdentifier( "notification_shade_shortcut", "id", context.packageName ) ) layoutParam.setObjectField( "topToTop", context.resources.getIdentifier( "notification_shade_shortcut", "id", context.packageName ) ) layoutParam.setObjectField( "bottomToBottom", context.resources.getIdentifier( "notification_shade_shortcut", "id", context.packageName ) ) mWeatherView = WeatherView(context, isDisplayCity).apply { setTextAppearance( context.resources.getIdentifier( "TextAppearance.StatusBar.Expanded.Clock.QuickSettingDate", "style", context.packageName ) ) layoutParams = layoutParam } viewGroup.addView(mWeatherView) (mWeatherView as WeatherView).setOnClickListener { try { val intent = Intent().apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK component = ComponentName( "com.miui.weather2", "com.miui.weather2.ActivityWeatherMain" ) } context.startActivity(intent) } catch (e: Exception) { XposedLogUtils.logE(TAG, e) } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/QQSGrid.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.content.res.Configuration import android.view.ViewGroup import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class QQSGrid : BaseHook() { override fun init() { val cols = mPrefsMap.getInt("system_control_center_old_qs_grid_columns", 5); val colsHorizontal = mPrefsMap.getInt("system_control_center_old_qs_grid_columns_horizontal", 6); loadClass("com.android.systemui.qs.MiuiQuickQSPanel").methodFinder().first { name == "setMaxTiles" && parameterCount == 1 }.createHook { before { val viewGroup = it.thisObject as ViewGroup val mConfiguration: Configuration = viewGroup.context.resources.configuration if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { it.args[0] = cols } else { it.args[0] = colsHorizontal } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/QQSGridOld.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; public class QQSGridOld extends BaseHook { @Override public void init() { int cols = mPrefsMap.getInt("system_control_center_old_qs_grid_column", 2); int colsResId = switch (cols) { case 3 -> R.integer.quick_quick_settings_num_rows_3; case 4 -> R.integer.quick_quick_settings_num_rows_4; case 5 -> R.integer.quick_quick_settings_num_rows_5; case 6 -> R.integer.quick_quick_settings_num_rows_6; case 7 -> R.integer.quick_quick_settings_num_rows_7; default -> R.integer.quick_quick_settings_num_rows_5; }; mResHook.setResReplacement("com.android.systemui", "integer", "quick_settings_qqs_count", colsResId); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/QSControlDetailBackgroundAlpha.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.graphics.drawable.Drawable import android.view.View import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.HookUtils import com.sevtinge.cemiuiler.utils.log.XposedLogUtils.logW import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers object QSControlDetailBackgroundAlpha : BaseHook() { override fun init() { val qSControlDetailBackgroundAlpha = mPrefsMap.getInt("system_ui_control_center_control_detail_background_alpha", 255) val qSControlDetailClass = findClassIfExists( "com.android.systemui.controlcenter.phone.detail.QSControlDetail" ) if (qSControlDetailClass != null) { XposedHelpers.findAndHookMethod( qSControlDetailClass, "updateBackground", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val mDetailContainer = HookUtils.getValueByField(param.thisObject, "mDetailContainer") as View if (mDetailContainer.background != null) { val smoothRoundDrawable = mDetailContainer.background smoothRoundDrawable.alpha = qSControlDetailBackgroundAlpha } } }) } val modalQSControlDetailClass = findClassIfExists( "com.android.systemui.statusbar.notification.modal.ModalQSControlDetail" ) if (modalQSControlDetailClass != null) { XposedHelpers.findAndHookMethod( modalQSControlDetailClass, "updateBackground", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val mDetailContainer = HookUtils.getValueByField(param.thisObject, "mDetailContainer") as View if (mDetailContainer.background != null) { val smoothRoundDrawable = mDetailContainer.background smoothRoundDrawable.alpha = qSControlDetailBackgroundAlpha } } }) } hookClassInPlugin { classLoader -> try { val smoothRoundDrawableClass = XposedHelpers.callMethod( classLoader, "loadClass", "miui.systemui.widget.SmoothRoundDrawable" ) ?: return@hookClassInPlugin XposedBridge.hookAllMethods( smoothRoundDrawableClass as Class<*>, "inflate", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { try { val currentDrawable = param.thisObject as Drawable currentDrawable.alpha = qSControlDetailBackgroundAlpha } catch (e: Throwable) { // Do Nothings. logW(TAG, e) } } }) } catch (e: Throwable) { logW(TAG, e) } } } private fun hookClassInPlugin(afterGetClassLoader: (classLoader: ClassLoader) -> Unit) { val pluginHandlerClass = findClassIfExists( "com.android.systemui.shared.plugins.PluginInstanceManager\$PluginHandler" ) if (pluginHandlerClass != null) { XposedBridge.hookAllMethods( pluginHandlerClass, "handleLoadPlugin", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val componentName = param.args[0] val className = XposedHelpers.callMethod(componentName, "getClassName") as String if (className != "miui.systemui.volume.VolumeDialogPlugin") { return } try { val pluginContextWrapper = HookUtils.getValueByField(param.result ?: return, "mPluginContext") ?: return val classLoader = XposedHelpers.callMethod( pluginContextWrapper, "getClassLoader" ) as ClassLoader afterGetClassLoader(classLoader) } catch (e: Throwable) { // Do Nothings. logW(TAG, e) } } }) return } val pluginActionManagerClass = findClassIfExists( "com.android.systemui.shared.plugins.PluginActionManager" ) if (pluginActionManagerClass != null) { XposedBridge.hookAllMethods( pluginActionManagerClass, "loadPluginComponent", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { val componentName = param.args[0] val className = XposedHelpers.callMethod(componentName, "getClassName") as String if (className != "miui.systemui.volume.VolumeDialogPlugin") { return } try { val pluginContextWrapper = HookUtils.getValueByField(param.result ?: return, "mPluginContext") ?: return val classLoader = XposedHelpers.callMethod( pluginContextWrapper, "getClassLoader" ) as ClassLoader afterGetClassLoader(classLoader) } catch (e: Throwable) { // Do Nothings. logW(TAG, e) } } }) return } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/QSGrid.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.content.res.Configuration import android.view.View import android.view.ViewGroup import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XposedHelpers class QSGrid : BaseHook() { override fun init() { val cols = mPrefsMap.getInt("system_control_center_old_qs_columns", 4) val colsHorizontal = mPrefsMap.getInt("system_control_center_old_qs_columns_horizontal", 5) val rows = mPrefsMap.getInt("system_control_center_old_qs_rows", 3) val rowsHorizontal = mPrefsMap.getInt("system_control_center_old_qs_rows_horizontal", 2) loadClass("com.android.systemui.qs.MiuiTileLayout").methodFinder().first { name == "updateColumns" }.createHook { after { val viewGroup = it.thisObject as ViewGroup val mConfiguration: Configuration = viewGroup.context.resources.configuration if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { XposedHelpers.setObjectField ( it.thisObject, "mColumns", cols ) } else { XposedHelpers.setObjectField ( it.thisObject, "mColumns", colsHorizontal ) } } } loadClass("com.android.systemui.qs.MiuiTileLayout").methodFinder().first { name == "updateResources" }.createHook { after { val viewGroup = it.thisObject as ViewGroup val mConfiguration: Configuration = viewGroup.context.resources.configuration if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { XposedHelpers.setObjectField ( it.thisObject, "mMaxAllowedRows", rows ) } else { XposedHelpers.setObjectField ( it.thisObject, "mMaxAllowedRows", rowsHorizontal ) } viewGroup.requestLayout() } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/QSGridLabels.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.content.res.Configuration; import android.view.View; import android.view.ViewGroup; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import java.util.ArrayList; import de.robv.android.xposed.XposedHelpers; public class QSGridLabels extends BaseHook { @Override public void init() { Helpers.hookAllMethods("com.android.systemui.qs.MiuiTileLayout", lpparam.classLoader, "addTile", new MethodHook() { @Override protected void before(MethodHookParam param) { updateLabelsVisibility(param.args[0], XposedHelpers.getIntField(param.thisObject, "mRows"), ((ViewGroup) param.thisObject).getResources().getConfiguration().orientation); } }); Helpers.hookAllMethods("com.android.systemui.qs.MiuiPagedTileLayout", lpparam.classLoader, "addTile", new MethodHook() { @Override @SuppressWarnings("unchecked") protected void before(MethodHookParam param) throws Throwable { ArrayList mPages = (ArrayList) XposedHelpers.getObjectField(param.thisObject, "mPages"); if (mPages == null) return; int mRows = 0; if (mPages.size() > 0) mRows = XposedHelpers.getIntField(mPages.get(0), "mRows"); updateLabelsVisibility(param.args[0], mRows, ((ViewGroup) param.thisObject).getResources().getConfiguration().orientation); } }); int rows = isMoreAndroidVersion(33) ? mPrefsMap.getInt("system_control_center_old_qs_rows", 1) : mPrefsMap.getInt("system_control_center_old_qs_row", 1); if (rows == 4) { Helpers.findAndHookMethod("com.android.systemui.qs.tileimpl.MiuiQSTileView", lpparam.classLoader, "createLabel", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ViewGroup mLabelContainer = (ViewGroup) XposedHelpers.getObjectField(param.thisObject, "mLabelContainer"); if (mLabelContainer != null) mLabelContainer.setPadding( mLabelContainer.getPaddingLeft(), Math.round(mLabelContainer.getResources().getDisplayMetrics().density * 2), mLabelContainer.getPaddingRight(), mLabelContainer.getPaddingBottom() ); } }); } } private static void updateLabelsVisibility(Object mRecord, int mRows, int orientation) { if (mRecord == null) return; Object tileView = XposedHelpers.getObjectField(mRecord, "tileView"); if (tileView != null) { ViewGroup mLabelContainer = null; try { mLabelContainer = (ViewGroup) XposedHelpers.getObjectField(tileView, "mLabelContainer"); } catch (Throwable ignore) { } if (mLabelContainer != null) { if (isMoreAndroidVersion(33)) { mLabelContainer.setVisibility( mPrefsMap.getBoolean("system_control_center_qs_tile_label") ? View.GONE : View.VISIBLE ); } else { mLabelContainer.setVisibility( mPrefsMap.getBoolean("system_control_center_qs_tile_label") || orientation == Configuration.ORIENTATION_PORTRAIT && mRows >= 5 || orientation == Configuration.ORIENTATION_LANDSCAPE && mRows >= 3 ? View.GONE : View.VISIBLE ); } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/QSGridOld.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; public class QSGridOld extends BaseHook { @Override public void init() { int cols = mPrefsMap.getInt("system_control_center_old_qs_column", 2); int rows = mPrefsMap.getInt("system_control_center_old_qs_row", 1); int colsRes = R.integer.quick_settings_num_columns_3; int rowsRes = R.integer.quick_settings_num_rows_4; switch (cols) { case 3 -> colsRes = R.integer.quick_settings_num_columns_3; case 4 -> colsRes = R.integer.quick_settings_num_columns_4; case 5 -> colsRes = R.integer.quick_settings_num_columns_5; case 6 -> colsRes = R.integer.quick_settings_num_columns_6; case 7 -> colsRes = R.integer.quick_settings_num_columns_7; } switch (rows) { case 2 -> rowsRes = R.integer.quick_settings_num_rows_2; case 3 -> rowsRes = R.integer.quick_settings_num_rows_3; case 4 -> rowsRes = R.integer.quick_settings_num_rows_4; case 5 -> rowsRes = R.integer.quick_settings_num_rows_5; } if (cols > 2) mResHook.setResReplacement("com.android.systemui", "integer", "quick_settings_num_columns", colsRes); if (rows > 1) mResHook.setResReplacement("com.android.systemui", "integer", "quick_settings_num_rows", rowsRes); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/RedirectToNotificationChannelSetting.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter import android.content.Context import android.content.Intent import android.os.UserHandle import android.provider.Settings import android.service.notification.StatusBarNotification import com.github.kyuubiran.ezxhelper.ClassUtils.getStaticObjectOrNullAs import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.EzXHelper.appContext import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.ObjectHelper.Companion.objectHelper import com.github.kyuubiran.ezxhelper.ObjectUtils.invokeMethodBestMatch import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object RedirectToNotificationChannelSetting : BaseHook() { override fun init() { var statusBarNotification: StatusBarNotification? = null loadClass("com.android.systemui.statusbar.notification.row.MiuiNotificationMenuRow") .methodFinder() .filterByName("onClickInfoItem").first().createHook { before { param -> param.thisObject.objectHelper { EzXHelper.initAppContext(getObjectOrNullAs("mContext")) statusBarNotification = getObjectOrNullAs("mSbn") } } after { statusBarNotification = null } } loadClass("com.android.systemui.statusbar.notification.NotificationSettingsHelper") .methodFinder() .filterByName("startAppNotificationSettings").first().createHook { before { param -> val intent = Intent(Intent.ACTION_MAIN) .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) .setClassName("com.android.settings", "com.android.settings.SubSettings") .putExtra( ":android:show_fragment", "com.android.settings.notification.ChannelNotificationSettings" ) .putExtra(Settings.EXTRA_APP_PACKAGE, statusBarNotification!!.packageName) .putExtra( Settings.EXTRA_CHANNEL_ID, statusBarNotification!!.notification.channelId ) .putExtra("app_uid", statusBarNotification!!.uid) .putExtra( Settings.EXTRA_CONVERSATION_ID, statusBarNotification!!.notification.shortcutId ) val userHandleCurrent = getStaticObjectOrNullAs( UserHandle::class.java, "CURRENT" ) invokeMethodBestMatch( appContext, "startActivityAsUser", null, intent, userHandleCurrent ) param.result = null } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/SmartHome.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import android.content.pm.ApplicationInfo; import android.widget.RelativeLayout; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import de.robv.android.xposed.XposedHelpers; public class SmartHome extends BaseHook { private ClassLoader mPluginLoader = null; @Override public void init() { findAndHookMethod("com.android.systemui.shared.plugins.PluginManagerImpl", "getClassLoader", ApplicationInfo.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ApplicationInfo appInfo = (ApplicationInfo) param.args[0]; if ("miui.systemui.plugin".equals(appInfo.packageName)) { if (mPluginLoader == null) { mPluginLoader = (ClassLoader) param.getResult(); Helpers.findAndHookMethod("miui.systemui.devicecontrols.ui.MiuiControlsUiControllerImpl", mPluginLoader, "updateOrientation", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { RelativeLayout mParent = (RelativeLayout) XposedHelpers.getObjectField(param.thisObject, "parent"); } }); } } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/SunlightMode.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.provider.Settings; import android.util.ArrayMap; import androidx.annotation.Nullable; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.utils.ShellUtils; import com.sevtinge.cemiuiler.utils.TileUtils; import com.sevtinge.cemiuiler.utils.log.AndroidLogUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Objects; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.XposedHelpers; public class SunlightMode extends TileUtils { public static String path = null; public static boolean mMode = false; public static boolean useSystem = false; public static int lastSunlight = 0; // public static int lastBrightnessMode = 0; // public static int maxSunlight = 0; public static int pathSunlight = 0; public static boolean intentListening = false; // public static boolean imOpenCustomMode = false; public static final String screenBrightness = "screen_brightness"; public static final String screenBrightnessEnable = "screen_brightness_enable"; public static final String screenBrightnessMode = "screen_brightness_mode"; public static final String screenBrightnessCustomMode = "screen_brightness_custom_mode"; public static final String sunlightMode = "sunlight_mode"; String mQSFactoryClsName = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "com.android.systemui.qs.tileimpl.MiuiQSFactory" : "com.android.systemui.qs.tileimpl.QSFactoryImpl"; @Override public void init() { modeSwitch(); setPath(); super.init(); } /*public void sLog(String log) { Log.i("SunlightMode", "sLog: " + log); }*/ public void modeSwitch() { int mode = mPrefsMap.getStringAsInt("system_control_center_sunshine_new_mode", 0); switch (mode) { case 1 -> mMode = false; case 2 -> mMode = true; } } @Override public boolean needCustom() { return true; } public void setPath() { String fileOne = "/sys/class/mi_display/disp-DSI-0/brightness_clone"; String fileTwo = "/sys/class/backlight/panel0-backlight/brightness"; File file = new File(fileOne); if (file.exists()) { path = fileOne; } else { File file1 = new File(fileTwo); if (file1.exists()) { path = fileTwo; } } /*ShellUtils.CommandResult commandResult = ShellUtils.execCommand("[ -f " + fileOne + " ]", true, false); if (commandResult.result == 0) { path = fileOne; } else { ShellUtils.CommandResult shell = ShellUtils.execCommand("[ -f " + fileOne + " ]", true, false); if (shell.result == 0) { path = fileTwo; } } sLog("tileCheck: shell result is: " + commandResult.result); intentListening = true;*/ if (path == null) { useSystem = true; XposedLogUtils.logE(TAG, "Missing directory, unable to set this mode: true"); } else { ShellUtils.execCommand("chmod 777 " + path, true, false); // XposedLogUtils.logI("setPath: im get file: " + path); } } @Override public Class customQSFactory() { return findClassIfExists(mQSFactoryClsName); } @Override public Class customClass() { return findClassIfExists("com.android.systemui.qs.tiles.PowerSaverTile"); } @Override public String[] customTileProvider() { String[] TileProvider = new String[3]; TileProvider[0] = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "powerSaverTileProvider" : "mPowerSaverTileProvider"; TileProvider[1] = isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU) ? "createTileInternal" : "interceptCreateTile"; TileProvider[2] = "createTile"; return TileProvider; } @Override public String customName() { return "custom_SUN"; } @Override public int customValue() { return R.string.system_control_center_sunshine_mode; } public void refreshState(Object o) { XposedHelpers.callMethod(o, "refreshState"); } @Override public void tileCheck(MethodHookParam param, String tileName) { param.setResult(true); } @Override public void tileLongClickIntent(MethodHookParam param, String tileName) { param.setResult(null); } @Override public boolean needAfter() { return false; } @Override public void tileClick(MethodHookParam param, String tileName) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); try { if (!mMode) { /*系统阳光模式*/ int systemMode = Settings.System.getInt(mContext.getContentResolver(), sunlightMode); if (systemMode == 1) { Settings.System.putInt(mContext.getContentResolver(), sunlightMode, 0); refreshState(param.thisObject); } else if (systemMode == 0) { Settings.System.putInt(mContext.getContentResolver(), sunlightMode, 1); refreshState(param.thisObject); } else { XposedLogUtils.logE(TAG, "ERROR Int For sunlight_mode"); } } else { if (!useSystem) { /*强制最高亮度*/ if (lastSunlight == 0 || Integer.parseInt(readAndWrit(null, false)) != pathSunlight) { // imOpenCustomMode = true; if (getBrightnessMode(mContext) == 1) { setCustomBrightnessMode(mContext, 1); } setBroadcastReceiver(mContext, param); lastSunlight = Integer.parseInt(readAndWrit(null, false)); readAndWrit("" + Integer.MAX_VALUE, true); /*Settings.System.putInt(mContext.getContentResolver(), screenBrightness, Integer.MAX_VALUE); if (maxSunlight == 0) maxSunlight = Settings.System.getInt(mContext.getContentResolver(), screenBrightness); sLog("tileClick: lastSunlight: " + lastSunlight + " pathSunlight: " + pathSunlight + " filter: " + filter); ShellUtils.CommandResult commandResult = ShellUtils.execCommand("sleep 0.8 && echo " + Integer.MAX_VALUE + " > " + path + " && cat " + path, true, true); try { pathSunlight = Integer.parseInt(commandResult.successMsg); } catch (NumberFormatException e) { logE("cant to int: " + pathSunlight); }*/ } else { // imOpenCustomMode = false; if (getCustomBrightnessMode(mContext) == 1) { setCustomBrightnessMode(mContext, 0); } // sLog("tileClick: comeback lastSunlight: " + lastSunlight + " pathSunlight: " + pathSunlight); unBroadcastReceiver(mContext, param); readAndWrit("" + lastSunlight, false); lastSunlight = 0; // 重置 } } else { /*系统Api最高亮度*/ if (lastSunlight == 0) { // imOpenCustomMode = true; if (getBrightnessMode(mContext) == 1) { setCustomBrightnessMode(mContext, 1); } setBroadcastReceiver(mContext, param); lastSunlight = Settings.System.getInt(mContext.getContentResolver(), screenBrightness); Settings.System.putInt(mContext.getContentResolver(), screenBrightness, Integer.MAX_VALUE); Settings.System.putInt(mContext.getContentResolver(), screenBrightnessEnable, 1); // pathSunlight = Settings.System.getInt(mContext.getContentResolver(), screenBrightness); // 不稳定 } else { // imOpenCustomMode = false; if (getCustomBrightnessMode(mContext) == 1) { setCustomBrightnessMode(mContext, 0); } unBroadcastReceiver(mContext, param); Settings.System.putInt(mContext.getContentResolver(), screenBrightness, lastSunlight); Settings.System.putInt(mContext.getContentResolver(), screenBrightnessEnable, 0); lastSunlight = 0; // 重置 } } refreshState(param.thisObject); } } catch (Settings.SettingNotFoundException e) { refreshState(param.thisObject); } } public static int getBrightnessMode(Context context) { try { return Settings.System.getInt(context.getContentResolver(), screenBrightnessMode); } catch (Settings.SettingNotFoundException e) { AndroidLogUtils.LogE("No Found Settings: ", e); return -1; } } public static void setBrightnessMode(Context context, int value) { Settings.System.putInt(context.getContentResolver(), screenBrightnessMode, value); } public static int getCustomBrightnessMode(Context context) { try { return Settings.System.getInt(context.getContentResolver(), screenBrightnessCustomMode); } catch (Settings.SettingNotFoundException e) { setCustomBrightnessMode(context, 0); AndroidLogUtils.LogE("No Found Settings: ", e); return -1; } } public static void setCustomBrightnessMode(Context context, int value) { Settings.System.putInt(context.getContentResolver(), screenBrightnessCustomMode, value); } public void setBroadcastReceiver(Context mContext, MethodHookParam param) { BroadcastReceiver broadcastReceiver = new Screen(); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); mContext.registerReceiver(broadcastReceiver, filter); // logE("setBroadcastReceiver: registerReceiver: " + broadcastReceiver + " filter: " + filter); XposedHelpers.setAdditionalInstanceField(param.thisObject, "broadcastReceiver", broadcastReceiver); intentListening = true; } public void unBroadcastReceiver(Context mContext, MethodHookParam param) { BroadcastReceiver broadcastReceiver = (BroadcastReceiver) XposedHelpers.getAdditionalInstanceField(param.thisObject, "broadcastReceiver"); // logE("unBroadcastReceiver: broadcastReceiver: " + broadcastReceiver); if (broadcastReceiver != null) { // logE("unBroadcastReceiver: unregisterReceiver: " + broadcastReceiver); mContext.unregisterReceiver(broadcastReceiver); intentListening = false; } } @Override public void tileListening(MethodHookParam param, String tileName) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); boolean mListening = (boolean) param.args[0]; // sLog("tileListening: mListening: " + mListening); if (mListening) { ContentObserver contentObserver = new ContentObserver(new Handler(mContext.getMainLooper())) { @Override public void onChange(boolean selfChange, @Nullable Uri uri) { super.onChange(selfChange, uri); if (uri != null) { String uriString = uri.toString(); String mUriString = Settings.System.getUriFor(screenBrightnessCustomMode).toString(); if (uriString.equals(mUriString)) { if (getBrightnessMode(mContext) == 0 && getCustomBrightnessMode(mContext) == 0) { setBrightnessMode(mContext, 1); } else if (getBrightnessMode(mContext) == 1 && getCustomBrightnessMode(mContext) == 1) { setBrightnessMode(mContext, 0); } } } refreshState(param.thisObject); } }; getCustomBrightnessMode(mContext); mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor(screenBrightness), false, contentObserver); mContext.getContentResolver().registerContentObserver(Settings.System.getUriFor(screenBrightnessCustomMode), false, contentObserver); XposedHelpers.setAdditionalInstanceField(param.thisObject, "tileListener", contentObserver); } else { // if (contentObserver != null) { // sLog("tileListening: im unregisterContentObserver: " + contentObserver); // mContext.getContentResolver().unregisterContentObserver(contentObserver); // } ContentObserver contentObserver = (ContentObserver) XposedHelpers.getAdditionalInstanceField(param.thisObject, "tileListener"); // sLog("tileListening: im unregisterContentObserver: " + contentObserver); mContext.getContentResolver().unregisterContentObserver(contentObserver); } } @Override public ArrayMap tileUpdateState(MethodHookParam param, Class mResourceIcon, String tileName) { int nowInt = 0; int nowSunlight; boolean isEnable = false; Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); try { Settings.System.getInt(mContext.getContentResolver(), sunlightMode); if (mMode) { try { Settings.System.getInt(mContext.getContentResolver(), screenBrightness); } catch (Settings.SettingNotFoundException e) { mMode = false; // sLog("tileCheck: Missing system API: " + screenBrightness); } } } catch (Settings.SettingNotFoundException e) { XposedLogUtils.logE(TAG, "tileUpdateState: Missing system API: " + sunlightMode); } try { if (!mMode) { nowInt = Settings.System.getInt(mContext.getContentResolver(), sunlightMode); } else { if (!useSystem) { // nowInt = Settings.System.getInt(mContext.getContentResolver(), screenBrightness); nowSunlight = Integer.parseInt(readAndWrit(null, false)); if (nowSunlight == pathSunlight) nowInt = 1; // if (nowInt == maxSunlight) { // nowInt = 1; // } else // sLog("tileUpdateState: nowInt is: " + nowInt + " pathSunlight: " + pathSunlight + " nowSunlight: " + nowSunlight); } else { nowSunlight = Settings.System.getInt(mContext.getContentResolver(), screenBrightnessEnable); if (nowSunlight == 1) nowInt = 1; } } if (nowInt == 1) isEnable = true; if (intentListening && !isEnable) { unBroadcastReceiver(mContext, param); } // sLog("tileUpdateState: isEnable is: " + isEnable); } catch (Settings.SettingNotFoundException e) { XposedLogUtils.logE(TAG, "tileUpdateState: Not Find sunlight_mode"); } ArrayMap tileResMap = new ArrayMap<>(); tileResMap.put("custom_SUN_Enable", isEnable ? 1 : 0); tileResMap.put("custom_SUN_ON", mResHook.addResource("ic_control_center_sunlight_mode_on", R.drawable.baseline_wb_sunny_24)); tileResMap.put("custom_SUN_OFF", mResHook.addResource("ic_control_center_sunlight_mode_off", R.drawable.baseline_wb_sunny_24)); return tileResMap; } public static String readAndWrit(String writ, boolean need) { String line; BufferedReader reader = null; BufferedWriter writer = null; StringBuilder builder = null; /*try { // 800毫秒获得丝滑转场效果,太好笑了,记录一下 Thread.sleep(need ? 800 : 400); } catch (InterruptedException e) { logE("sleep error: " + e); }*/ if (writ != null) { try { writer = new BufferedWriter(new FileWriter(path, false)); writer.write(writ); } catch (IOException e) { AndroidLogUtils.LogE("SunlightMode", "error to writer: " + path + " ", e); } finally { try { if (writer != null) { writer.close(); } } catch (IOException e) { AndroidLogUtils.LogE("SunlightMode", "close writer error: ", e); } } } try { reader = new BufferedReader(new FileReader(path)); builder = new StringBuilder(); while ((line = reader.readLine()) != null) { builder.append(line); } } catch (IOException e) { AndroidLogUtils.LogE("SunlightMode", "error to read: " + path + " ", e); } finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { AndroidLogUtils.LogE("SunlightMode", "close reader error: ", e); } } if (builder != null) { // logE("get string: " + builder); if (need) pathSunlight = Integer.parseInt(builder.toString()); return builder.toString(); } return null; } public static class Screen extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 息屏还原,按照之前的逻辑写的,如果需要再改 if (Objects.equals(intent.getAction(), Intent.ACTION_SCREEN_OFF)) { // Log.i("SunlightMode", "onReceive: run 1"); // AndroidLogUtils.LogE("SunlightMode", "onReceive 1: " + lastSunlight + " use: " + useSystem, null); if (lastSunlight != 0) { // AndroidLogUtils.LogE("SunlightMode", "onReceive 2: " + lastSunlight + " use: " + useSystem, null); if (!useSystem) { // Log.i("SunlightMode", "onReceive: run"); // Settings.System.putInt(context.getContentResolver(), screenBrightness, lastSunlight); readAndWrit("" + lastSunlight, false); } else { Settings.System.putInt(context.getContentResolver(), screenBrightness, lastSunlight); Settings.System.putInt(context.getContentResolver(), screenBrightnessEnable, 0); } lastSunlight = 0; // 重置 if (getCustomBrightnessMode(context) == 1) { setBrightnessMode(context, 1); setCustomBrightnessMode(context, 0); } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/controlcenter/SwitchCCAndNotification.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.controlcenter; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidU; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.view.MotionEvent; import android.widget.FrameLayout; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import de.robv.android.xposed.XposedHelpers; public class SwitchCCAndNotification extends BaseHook { @Override public void init() { Helpers.findAndHookMethod( "com.android.systemui.statusbar.phone.MiuiPhoneStatusBarView", lpparam.classLoader, "handleEvent", MotionEvent.class, new MethodHook() { @Override protected void before(MethodHookParam param) { boolean useCC = (boolean) XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "mPanelController"), "isExpandable"); if (useCC) { FrameLayout bar = (FrameLayout) param.thisObject; Object mControlPanelWindowManager = XposedHelpers.getObjectField(param.thisObject, "mControlPanelWindowManager"); boolean dispatchToControlPanel = (boolean) XposedHelpers.callMethod(mControlPanelWindowManager, "dispatchToControlPanel", param.args[0], bar.getWidth()); if (isAndroidU()) { XposedHelpers.setObjectField(mControlPanelWindowManager, "mTransToControlPanel", dispatchToControlPanel); } else { XposedHelpers.callMethod(mControlPanelWindowManager, "setTransToControlPanel", dispatchToControlPanel); } param.setResult(dispatchToControlPanel); return; } param.setResult(false); } }); Helpers.findAndHookMethod( "com.android.systemui.controlcenter.phone.ControlPanelWindowManager", lpparam.classLoader, "dispatchToControlPanel", MotionEvent.class, float.class, new MethodHook() { @Override protected void before(MethodHookParam param) { boolean added = XposedHelpers.getBooleanField(param.thisObject, "added"); if (added) { boolean useCC; if (isMoreAndroidVersion(33)) { useCC = XposedHelpers.getBooleanField(XposedHelpers.getObjectField(param.thisObject, "mControlCenterController"), "useControlCenter"); } else { useCC = (boolean) XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "mControlCenterController"), "isExpandable"); } if (useCC) { MotionEvent motionEvent = (MotionEvent) param.args[0]; if (motionEvent.getActionMasked() == 0) { XposedHelpers.setObjectField(param.thisObject, "mDownX", motionEvent.getRawX()); } Object controlCenterWindowView = XposedHelpers.getObjectField(param.thisObject, "mControlPanel"); if (controlCenterWindowView == null) { param.setResult(false); } else { float mDownX = XposedHelpers.getFloatField(param.thisObject, "mDownX"); float width = (float) param.args[1]; if (mDownX < width / 2.0f) { param.setResult(XposedHelpers.callMethod(controlCenterWindowView, "handleMotionEvent", motionEvent, true)); } else { param.setResult(false); } } return; } } param.setResult(false); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/AddBlurEffectToLockScreen.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import android.animation.ValueAnimator import android.graphics.drawable.LayerDrawable import android.view.ViewGroup import android.widget.ImageView import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.HookUtils import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidU import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers object AddBlurEffectToLockScreen : BaseHook() { override fun init() { val miuiNotificationPanelViewControllerClass = findClassIfExists( if (isAndroidU()) "com.android.systemui.shade.MiuiNotificationPanelViewController" else "com.android.systemui.statusbar.phone.MiuiNotificationPanelViewController" ) ?: return val keyguardBottomAreaViewClass = findClassIfExists( "com.android.systemui.statusbar.phone.KeyguardBottomAreaView" ) ?: return val lockScreenMagazineControllerClass = findClassIfExists( "com.android.keyguard.magazine.LockScreenMagazineController" ) ?: return // to com.sevtinge.cemiuiler.module.systemui.lockscreen.BlurButton /*XposedBridge.hookAllMethods( keyguardBottomAreaViewClass, "onAttachedToWindow", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { /*if (!isDefaultLockScreenTheme()) { return }*/ val mLeftAffordanceView = HookUtils.getValueByField( param.thisObject, "mLeftAffordanceView" ) as ImageView val mRightAffordanceView = HookUtils.getValueByField( param.thisObject, "mRightAffordanceView" ) as ImageView val keyguardBottomAreaView = param.thisObject as View val leftBlurDrawable = HookUtils.createBlurDrawable( keyguardBottomAreaView, 40, 100, Color.argb(60, 255, 255, 255) ) val leftLayerDrawable = LayerDrawable(arrayOf(leftBlurDrawable)) val rightBlurDrawable = HookUtils.createBlurDrawable( keyguardBottomAreaView, 40, 100, Color.argb(60, 255, 255, 255) ) val rightLayerDrawable = LayerDrawable(arrayOf(rightBlurDrawable)) leftLayerDrawable.setLayerInset(0, 40, 40, 40, 40) rightLayerDrawable.setLayerInset(0, 40, 40, 40, 40) mLeftAffordanceView.background = leftLayerDrawable mRightAffordanceView.background = rightLayerDrawable } })*/ XposedBridge.hookAllMethods( miuiNotificationPanelViewControllerClass, "setBouncerShowingFraction", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) { return } val mKeyguardBouncerShowing = HookUtils.getValueByField( param.thisObject, "mKeyguardBouncerShowing" ) as Boolean val mKeyguardBottomArea = XposedHelpers.callMethod(param.thisObject, "getKeyguardBottomArea") val mLeftAffordanceView = HookUtils.getValueByField( mKeyguardBottomArea, "mLeftAffordanceView" ) as ImageView val mRightAffordanceView = HookUtils.getValueByField( mKeyguardBottomArea, "mRightAffordanceView" ) as ImageView if (mLeftAffordanceView.background is LayerDrawable) { val layerDrawable = mLeftAffordanceView.background as LayerDrawable val blurDrawable = layerDrawable.getDrawable(0) XposedHelpers.callMethod( blurDrawable, "setVisible", !mKeyguardBouncerShowing, false ) } if (mRightAffordanceView.background is LayerDrawable) { val layerDrawable = mRightAffordanceView.background as LayerDrawable val blurDrawable = layerDrawable.getDrawable(0) XposedHelpers.callMethod( blurDrawable, "setVisible", !mKeyguardBouncerShowing, false ) } } }) XposedBridge.hookAllMethods( miuiNotificationPanelViewControllerClass, "updateKeyguardElementAlpha", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) { return } val mNotificationStackScroller = HookUtils.getValueByField( param.thisObject, "mNotificationStackScroller" ) ?: return val mKeyguardBouncerShowing = HookUtils.getValueByField( param.thisObject, "mKeyguardBouncerShowing" ) ?: return mNotificationStackScroller as ViewGroup mKeyguardBouncerShowing as Boolean val keyguardContentsAlpha = XposedHelpers.callMethod( param.thisObject, "getKeyguardContentsAlpha" ) as Float val drawableAlpha = keyguardContentsAlpha * 255 val mKeyguardBottomArea = XposedHelpers.callMethod(param.thisObject, "getKeyguardBottomArea") val mLeftAffordanceView = HookUtils.getValueByField( mKeyguardBottomArea, "mLeftAffordanceView" ) as ImageView val mRightAffordanceView = HookUtils.getValueByField( mKeyguardBottomArea, "mRightAffordanceView" ) as ImageView if (mLeftAffordanceView.background is LayerDrawable) { val layerDrawable = mLeftAffordanceView.background as LayerDrawable val blurDrawable = layerDrawable.getDrawable(0) XposedHelpers.callMethod( blurDrawable, "setAlpha", drawableAlpha.toInt() ) } if (mRightAffordanceView.background is LayerDrawable) { val layerDrawable = mRightAffordanceView.background as LayerDrawable val blurDrawable = layerDrawable.getDrawable(0) XposedHelpers.callMethod( blurDrawable, "setAlpha", drawableAlpha.toInt() ) } } }) // 控制中心异常 /*XposedBridge.hookAllMethods( keyguardMoveHelperClass, "setTranslation", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) { return } val mCurrentScreen = HookUtils.getValueByField(param.thisObject, "mCurrentScreen") as Int val mLeftViewBg = HookUtils.getValueByField(param.thisObject, "mLeftViewBg") as ImageView mLeftViewBg.setImageDrawable(null) mLeftViewBg.setBackgroundColor(Color.TRANSPARENT) val transitionX = param.args[0] as Float val screenWidth = XposedHelpers.callMethod( param.thisObject, "getScreenWidth" ) as Float var alpha = (transitionX / screenWidth) * 255 if (mCurrentScreen != 1) { alpha += 255 } if (alpha > 255 || alpha < 0) { return } val drawableAlpha = (255 - alpha).toInt() var blurRadius = (transitionX / screenWidth) * 80 var colorAlpha = (transitionX / screenWidth) * 50 if (mCurrentScreen != 1) { blurRadius += 80 colorAlpha += 50 } val mFaceUnlockView = HookUtils.getValueByField(param.thisObject, "mFaceUnlockView") ?: return mFaceUnlockView as View if (mFaceUnlockView.parent == null || mFaceUnlockView.parent.parent == null) { return } val targetView = mFaceUnlockView.parent.parent as View if (blurRadius in 1f..81f) { if (HookUtils.isBlurDrawable(targetView.background)) { XposedHelpers.callMethod( targetView.background, "setBlurRadius", blurRadius.toInt() ) XposedHelpers.callMethod( targetView.background, "setColor", Color.argb(colorAlpha.toInt(), 0, 0, 0) ) } else { targetView.background = HookUtils.createBlurDrawable( targetView, blurRadius.toInt(), 0, Color.argb(colorAlpha.toInt(), 0, 0, 0) ) } } else { targetView.background = null } val mNotificationPanelViewController = HookUtils.getValueByField( param.thisObject, "mNotificationPanelViewController" ) ?: return val mNotificationStackScroller = HookUtils.getValueByField( mNotificationPanelViewController, "mNotificationStackScroller" ) ?: return mNotificationStackScroller as ViewGroup val mKeyguardBottomArea = XposedHelpers.callMethod( mNotificationPanelViewController, "getKeyguardBottomArea" ) val mLeftAffordanceView = HookUtils.getValueByField( mKeyguardBottomArea, "mLeftAffordanceView" ) as ImageView val mRightAffordanceView = HookUtils.getValueByField( mKeyguardBottomArea, "mRightAffordanceView" ) as ImageView if (mLeftAffordanceView.background is LayerDrawable) { val layerDrawable = mLeftAffordanceView.background as LayerDrawable layerDrawable.alpha = drawableAlpha } if (mRightAffordanceView.background is LayerDrawable) { val layerDrawable = mRightAffordanceView.background as LayerDrawable layerDrawable.alpha = drawableAlpha } } }) */ // 锁屏过渡至桌面模糊异常 /* XposedBridge.hookAllMethods( baseKeyguardMoveHelperClass, "doPanelViewAnimation", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) { return } val mNotificationPanelViewController = HookUtils.getValueByField( param.thisObject, "mNotificationPanelViewController" ) ?: return val panelView = XposedHelpers.callMethod( mNotificationPanelViewController, "getPanelView" ) ?: return panelView as View if (panelView.parent == null) { return } val targetBlurView = panelView.parent as View val isOnKeyguard = XposedHelpers.callMethod( mNotificationPanelViewController, "isOnKeyguard" ) as Boolean if (!isOnKeyguard) { if (HookUtils.isBlurDrawable(targetBlurView.background)) { targetBlurView.background = null } return } val mKeyguardBouncerShowing = HookUtils.getValueByField( mNotificationPanelViewController, "mKeyguardBouncerShowing" ) as Boolean if (mKeyguardBouncerShowing) { return } val mTranslationPer = HookUtils.getValueByField(param.thisObject, "mTranslationPer") as Float val f2 = 1.0f - (1.0f - mTranslationPer) * (1.0f - mTranslationPer) val blurRadius = f2 * 50 if (blurRadius > 0f) { if (HookUtils.isBlurDrawable(targetBlurView.background)) { XposedHelpers.callMethod( targetBlurView.background, "setBlurRadius", blurRadius.toInt() ) } else { targetBlurView.background = HookUtils.createBlurDrawable(targetBlurView, blurRadius.toInt(), 0) } } else if (!mKeyguardBouncerShowing) { targetBlurView.background = null } } }) */ XposedBridge.hookAllMethods( miuiNotificationPanelViewControllerClass, "onBouncerShowingChanged", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) { return } val isBouncerShowing = param.args[0] as Boolean val mBouncerFractionAnimator = HookUtils.getValueByField( param.thisObject, "mBouncerFractionAnimator" ) ?: return mBouncerFractionAnimator as ValueAnimator if (isBouncerShowing) { val mKeyguardBouncerFractionField = miuiNotificationPanelViewControllerClass.getDeclaredField("mKeyguardBouncerFraction") mKeyguardBouncerFractionField.isAccessible = true mKeyguardBouncerFractionField.set(param.thisObject, 1f) } } }) XposedBridge.hookAllMethods( lockScreenMagazineControllerClass, "setViewsAlpha", object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) { return } val alpha = param.args[0] as Float val drawableAlpha = alpha * 255 if (drawableAlpha < 0 || drawableAlpha > 255) { return } val mNotificationStackScrollLayout = HookUtils.getValueByField( param.thisObject, "mNotificationStackScrollLayout" ) ?: return // NotificationStackScrollLayoutController val mController = HookUtils.getValueByField(mNotificationStackScrollLayout, "mController") ?: return val mPanelViewController = HookUtils.getValueByField(mController, "mPanelViewController") ?: return val mKeyguardBottomArea = XposedHelpers.callMethod( mPanelViewController, "getKeyguardBottomArea" ) ?: return val mLeftAffordanceView = HookUtils.getValueByField( mKeyguardBottomArea, "mLeftAffordanceView" ) as ImageView val mRightAffordanceView = HookUtils.getValueByField( mKeyguardBottomArea, "mRightAffordanceView" ) as ImageView if (mLeftAffordanceView.background is LayerDrawable) { val layerDrawable = mLeftAffordanceView.background as LayerDrawable layerDrawable.alpha = drawableAlpha.toInt() } if (mRightAffordanceView.background is LayerDrawable) { val layerDrawable = mRightAffordanceView.background as LayerDrawable layerDrawable.alpha = drawableAlpha.toInt() } } }) XposedBridge.hookAllMethods( keyguardBottomAreaViewClass, "setDozing", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { if (!isDefaultLockScreenTheme()) { return } val isDozing = param.args[0] as Boolean val mLeftAffordanceView = HookUtils.getValueByField( param.thisObject, "mLeftAffordanceView" ) as ImageView val mRightAffordanceView = HookUtils.getValueByField( param.thisObject, "mRightAffordanceView" ) as ImageView if (mLeftAffordanceView.background == null || mRightAffordanceView.background == null) { return } val leftLayerDrawable = mLeftAffordanceView.background val rightLayerDrawable = mRightAffordanceView.background if (leftLayerDrawable is LayerDrawable && rightLayerDrawable is LayerDrawable) { val leftBlurDrawable = leftLayerDrawable.getDrawable(0) ?: return val rightBlurDrawable = rightLayerDrawable.getDrawable(0) ?: return XposedHelpers.callMethod( leftBlurDrawable, "setVisible", !isDozing, false ) XposedHelpers.callMethod( rightBlurDrawable, "setVisible", !isDozing, false ) } } }) } fun isDefaultLockScreenTheme(): Boolean { val miuiKeyguardUtilsClass = findClassIfExists( if (isAndroidU()) "com.miui.systemui.util.CommonUtil" else "com.android.keyguard.utils.MiuiKeyguardUtils" ) ?: return true return XposedHelpers.callStaticMethod( miuiKeyguardUtilsClass, "isDefaultLockScreenTheme" ) as Boolean } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/BlurButton.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import android.app.KeyguardManager import android.content.Context import android.graphics.Color import android.graphics.drawable.LayerDrawable import android.view.View import android.widget.ImageView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClassOrNull import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.ObjectUtils import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.HookUtils.createBlurDrawable object BlurButton : BaseHook() { override fun init() { lateinit var mLeftAffordanceView: ImageView lateinit var mRightAffordanceView: ImageView lateinit var keyguardBottomAreaView: View loadClassOrNull( "com.android.systemui.statusbar.phone.KeyguardBottomAreaView" )!!.methodFinder() .filter { name in setOf( "onAttachedToWindow", "onDetachedFromWindow", "updateRightAffordanceIcon", "updateLeftAffordanceIcon" ) }.toList().createHooks { after { param -> mLeftAffordanceView = ObjectUtils.getObjectOrNullAs(param.thisObject, "mLeftAffordanceView")!! mRightAffordanceView = ObjectUtils.getObjectOrNullAs(param.thisObject, "mRightAffordanceView")!! keyguardBottomAreaView = param.thisObject as View // Your blur logic val context = keyguardBottomAreaView.context ?: return@after val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager if (keyguardManager.isKeyguardLocked) { val leftBlurDrawable = createBlurDrawable( keyguardBottomAreaView, 40, 100, Color.argb(60, 255, 255, 255) ) val leftLayerDrawable = LayerDrawable(arrayOf(leftBlurDrawable)) val rightBlurDrawable = createBlurDrawable( keyguardBottomAreaView, 40, 100, Color.argb(60, 255, 255, 255) ) val rightLayerDrawable = LayerDrawable(arrayOf(rightBlurDrawable)) leftLayerDrawable.setLayerInset(0, 40, 40, 40, 40) rightLayerDrawable.setLayerInset(0, 40, 40, 40, 40) mLeftAffordanceView.background = leftLayerDrawable mRightAffordanceView.background = rightLayerDrawable } else { mLeftAffordanceView.background = null mRightAffordanceView.background = null } } } /*var mLeftAffordanceView: WeakReference? = null var mRightAffordanceView: WeakReference? = null var keyguardBottomAreaView: WeakReference? = null var handler = Handler(Looper.getMainLooper()) var needUpdate = true // from com.sevtinge.cemiuiler.module.systemui.lockscreen.AddBlurEffectToLockScreen val keyguardBottomAreaViewClass = findClassIfExists("com.android.systemui.statusbar.phone.KeyguardBottomAreaView") ?: return XposedBridge.hookAllMethods( keyguardBottomAreaViewClass, "onAttachedToWindow", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { mLeftAffordanceView = WeakReference( getValueByField(param.thisObject, "mLeftAffordanceView") as ImageView ) mRightAffordanceView = WeakReference( getValueByField(param.thisObject, "mRightAffordanceView") as ImageView ) keyguardBottomAreaView = WeakReference(param.thisObject as View) } }) fun createBlurLayerDrawable(view: View, color: Int): Array { val blurDrawable = createBlurDrawable(view, 40, 100, color) val leftLayerDrawable = LayerDrawable(arrayOf(blurDrawable)).apply { setLayerInset(0, 40, 40, 40, 40) } val rightLayerDrawable = LayerDrawable(arrayOf(blurDrawable)).apply { setLayerInset(0, 40, 40, 40, 40) } return arrayOf(leftLayerDrawable, rightLayerDrawable) } // 已摆烂,剩下数组异常问题(会多生成一个 0 的数组,导致抛出 ArrayIndexOutOfBoundsException 异常),感觉我没能力修好( // 性能优化得差不多了 val timer = Timer() timer.scheduleAtFixedRate(object : TimerTask() { override fun run() { val context = keyguardBottomAreaView?.get()?.context ?: return val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager if (keyguardManager.isKeyguardLocked) { if (needUpdate) { val message = Message.obtain() message.obj = true handler.sendMessage(message) needUpdate = false } } else { if (needUpdate) { val message = Message.obtain() message.obj = false handler.sendMessage(message) needUpdate = false } } } }, 0, 100) handler = object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { val updateFlag = msg.obj as? Boolean if (updateFlag != null) { if (updateFlag) { val blurColor = Color.argb(60, 255, 255, 255) keyguardBottomAreaView?.get()?.let { view -> val layerDrawables = createBlurLayerDrawable(view, blurColor) mLeftAffordanceView?.get()?.background = layerDrawables[0] mRightAffordanceView?.get()?.background = layerDrawables[1] } } else { mLeftAffordanceView?.get()?.background = null mRightAffordanceView?.get()?.background = null } needUpdate = true } } }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/ChargingCVP.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import android.annotation.SuppressLint import android.app.AndroidAppHelper import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.os.BatteryManager import android.os.Handler import android.os.PowerManager import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.invokeStaticMethodBestMatch import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.ClassUtils.loadClassOrNull import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.ObjectUtils.invokeMethodBestMatch import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.getAndroidVersion import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidU import com.sevtinge.cemiuiler.utils.devicesdk.isMoreAndroidVersion import de.robv.android.xposed.XposedHelpers import java.io.BufferedReader import java.io.FileReader import java.math.BigDecimal import java.math.RoundingMode import kotlin.math.abs object ChargingCVP : BaseHook() { @SuppressLint("SetTextI18n") override fun init() { // 去除单行限制,Android13 以上扩展一个刷新频率,Android12 的后面再看看情况 if (getAndroidVersion() >= 33) { val clazzDependency = loadClass("com.android.systemui.Dependency") val clazzKeyguardIndicationController = loadClass("com.android.systemui.statusbar.KeyguardIndicationController") loadClassOrNull("com.android.systemui.statusbar.phone.KeyguardIndicationTextView")?.constructors ?.createHooks { after { param -> (param.thisObject as TextView).isSingleLine = false val screenOnOffReceiver = @SuppressLint("ServiceCast") object : BroadcastReceiver() { val keyguardIndicationController = if (isAndroidU()) loadClass("com.android.systemui.statusbar.KeyguardIndicationController") else invokeStaticMethodBestMatch( clazzDependency, "get", null, clazzKeyguardIndicationController)!! val handler = Handler((param.thisObject as TextView).context.mainLooper) val runnable = object : Runnable { override fun run() { if (isAndroidU()) XposedHelpers.callStaticMethod(loadClass("com.android.systemui.statusbar.KeyguardIndicationController"), "updatePowerIndication") else invokeMethodBestMatch(keyguardIndicationController, "updatePowerIndication") handler.postDelayed( this, mPrefsMap.getInt("system_ui_statusbar_lock_screen_show_spacing", 6) / 2 * 1000L ) } } init { if (((param.thisObject as TextView).context.getSystemService(Context.POWER_SERVICE) as PowerManager).isInteractive) { handler.post(runnable) } } override fun onReceive(context: Context, intent: Intent) { when (intent.action) { Intent.ACTION_SCREEN_ON -> { handler.post(runnable) } Intent.ACTION_SCREEN_OFF -> { handler.removeCallbacks(runnable) } } } } with(param.thisObject as TextView) { val filter = IntentFilter().apply { addAction(Intent.ACTION_SCREEN_ON) addAction(Intent.ACTION_SCREEN_OFF) } context.registerReceiver(screenOnOffReceiver, filter) } } } } else { loadClassOrNull("com.android.systemui.statusbar.phone.KeyguardIndicationTextView")?.constructors ?.createHooks { after { (it.thisObject as TextView).isSingleLine = false } } } // 修改底部文本信息 val mBottomChargeClass by lazy { when { isMoreAndroidVersion(34) -> "com.miui.charge.ChargeUtils" else -> "com.android.keyguard.charge.ChargeUtils" } } loadClass(mBottomChargeClass).methodFinder() .filterByName("getChargingHintText") /*.filterByParamTypes( Context::class.java, Boolean::class.javaPrimitiveType, Int::class.javaPrimitiveType )*/ .first().createHook { after { it.result?.let { result -> it.result = result as String + getCVP() } } } } private fun getCVP(): String { // 获取电流信息 val batteryManager = AndroidAppHelper.currentApplication() .getSystemService(Context.BATTERY_SERVICE) as BatteryManager val current = abs(batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW) / 1000) var voltage = 0.0 var temp = 0.0 kotlin.runCatching { // 获取电压信息 val voltageNow = BufferedReader(FileReader("/sys/class/power_supply/battery/voltage_now")) voltage = BigDecimal(voltageNow.readLine().toDouble() / 1000.0).setScale(1, RoundingMode.HALF_UP).toDouble() // 获取电池温度信息 val temNow = BufferedReader(FileReader("/sys/class/power_supply/battery/temp")) temp = BigDecimal(temNow.readLine().toDouble() / 10.0).setScale(1, RoundingMode.HALF_UP).toDouble() } // 计算功率信息 val powerAll = abs((current * voltage) / 1000f / 1000f) val power = String.format("%.2f", powerAll) // 电流展示逻辑设置 val mCurrent = if (mPrefsMap.getBoolean("system_ui_show_charging_c_more")) { "$current mA" } else { "${String.format("%.1f", abs(current / 1000f))} A" } val mVoltage = "${String.format("%.1f", abs(voltage / 1000f))} V" // 电池温度是否展示 val mTemp = if (mPrefsMap.getBoolean("system_ui_show_battery_temperature")) " · $temp ℃" else "" // 判断充满信息是否归零 val showBattery = if (current == 0) { mTemp } else { "$mTemp\n$mCurrent · $mVoltage · $power W" } // 输出展示信息 return showBattery } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/ClockDisplaySeconds.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import android.annotation.SuppressLint import android.content.Context import android.os.Handler import android.provider.Settings import android.util.Log import android.widget.LinearLayout import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.MemberExtensions.paramCount import com.github.kyuubiran.ezxhelper.finders.ConstructorFinder.`-Static`.constructorFinder import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.getObjectFieldAs import de.robv.android.xposed.XC_MethodHook import java.lang.reflect.Method import java.text.SimpleDateFormat import java.util.* object ClockDisplaySeconds : BaseHook() { private var nowTime: Date = Calendar.getInstance().time override fun init() { loadClass("com.miui.clock.MiuiBaseClock").constructorFinder().first { paramCount == 2 }.createHook { after { try { val viewGroup = it.thisObject as LinearLayout val d: Method = viewGroup.javaClass.getDeclaredMethod("updateTime") val r = Runnable { d.isAccessible = true d.invoke(viewGroup) } class T : TimerTask() { override fun run() { Handler(viewGroup.context.mainLooper).post(r) } } Timer().scheduleAtFixedRate(T(), 1000 - System.currentTimeMillis() % 1000, 1000) } catch (_: Exception) { } } } loadClass("com.miui.clock.MiuiLeftTopClock").methodFinder().first { name == "updateTime" }.createHook { after { updateTime(it, false) } } loadClass("com.miui.clock.MiuiCenterHorizontalClock").methodFinder().first { name == "updateTime" }.createHook { after { updateTime(it, false) } } loadClass("com.miui.clock.MiuiLeftTopLargeClock").methodFinder().first { name == "updateTime" }.createHook { after { updateTime(it, false) } } loadClass("com.miui.clock.MiuiVerticalClock").methodFinder().first { name == "updateTime" }.createHook { after { updateTime(it, true) } } } private fun updateTime(it: XC_MethodHook.MethodHookParam, isVertical: Boolean) { val textV = it.thisObject.getObjectFieldAs("mTimeText") val c: Context = textV.context Log.d("lock_screen_clock_display_seconds", "updateTime: ${it.thisObject.javaClass.simpleName}") val is24 = Settings.System.getString(c.contentResolver, Settings.System.TIME_12_24) == "24" nowTime = Calendar.getInstance().time textV.text = getTime(is24, isVertical) } @SuppressLint("SimpleDateFormat") private fun getTime(is24: Boolean, isVertical: Boolean): String { var timePattern = "" timePattern += if (isVertical) { // 垂直 if (is24) "HH\nmm\nss" else "hh\nmm\nss" } else { // 水平 if (is24) "HH:mm:ss" else "h:mm:ss" } timePattern = SimpleDateFormat(timePattern).format(nowTime) return timePattern } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/ForceClockUseSystemFontsHook.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import android.graphics.Typeface import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.getObjectFieldAs object ForceClockUseSystemFontsHook : BaseHook() { override fun init() { loadClass("com.miui.clock.MiuiBaseClock").methodFinder().filter { name == "updateViewsTextSize" }.toList().createHooks { after { param -> val mTimeText = param.thisObject.getObjectFieldAs("mTimeText") mTimeText.typeface = Typeface.DEFAULT } } loadClass("com.miui.clock.MiuiLeftTopLargeClock").methodFinder().filter { name == "onLanguageChanged" && parameterTypes == String::class.java }.toList().createHooks { after { param -> val mTimeText = param.thisObject.getObjectFieldAs("mCurrentDateLarge") mTimeText.typeface = Typeface.DEFAULT } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/HideLockScreenHint.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers import com.sevtinge.cemiuiler.utils.devicesdk.isMoreAndroidVersion import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedHelpers object HideLockScreenHint : BaseHook() { override fun init() { val hook: MethodHook = object : MethodHook() { @Throws(Throwable::class) override fun before(param: MethodHookParam) { XposedHelpers.setObjectField(param.thisObject, "mUpArrowIndication", null) } } if (isMoreAndroidVersion(33)) { Helpers.findAndHookMethod( "com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController", lpparam.classLoader, "hasIndicationsExceptResting", XC_MethodReplacement.returnConstant(true) ) } else { Helpers.findAndHookMethod( "com.android.systemui.statusbar.KeyguardIndicationController", lpparam.classLoader, "updateIndication", Boolean::class.javaPrimitiveType, Boolean::class.javaPrimitiveType, hook ) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/HideLockScreenStatusBar.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import android.view.View import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers import com.sevtinge.cemiuiler.utils.devicesdk.isMoreAndroidVersion import de.robv.android.xposed.XposedHelpers object HideLockScreenStatusBar : BaseHook() { override fun init() { val statusBarClass = if (isMoreAndroidVersion(33)) "com.android.systemui.statusbar.phone.CentralSurfacesImpl" else "com.android.systemui.statusbar.phone.StatusBar" Helpers.hookAllMethods(statusBarClass, lpparam.classLoader, "makeStatusBarView", object : MethodHook() { override fun after(param: MethodHookParam) { val mKeyguardStatusBar = XposedHelpers.getObjectField( XposedHelpers.getObjectField( param.thisObject, "mNotificationPanelViewController" ), "mKeyguardStatusBar" ) as View mKeyguardStatusBar.translationY = -999f } } ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/HideLockscreenZenMode.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object HideLockscreenZenMode : BaseHook() { override fun init() { loadClass("com.android.systemui.statusbar.notification.zen.ZenModeViewController", lpparam.classLoader) .methodFinder().first { name == "shouldBeVisible" }.createHook { returnConstant(false) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/LockScreenDoubleTapToSleep.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import android.app.KeyguardManager import android.content.Context import android.os.SystemClock import android.view.MotionEvent import android.view.View import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidU import de.robv.android.xposed.XposedHelpers import de.robv.android.xposed.XposedHelpers.getAdditionalInstanceField import de.robv.android.xposed.XposedHelpers.setAdditionalInstanceField object LockScreenDoubleTapToSleep : BaseHook() { override fun init() { loadClass( if (isAndroidU()) "com.android.systemui.shade.NotificationsQuickSettingsContainer" else "com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer").methodFinder().first { name == "onFinishInflate" }.createHook { before { val view = it.thisObject as View setAdditionalInstanceField(view, "currentTouchTime", 0L) setAdditionalInstanceField(view, "currentTouchX", 0f) setAdditionalInstanceField(view, "currentTouchY", 0f) view.setOnTouchListener(View.OnTouchListener { v, event -> if (event.action != MotionEvent.ACTION_DOWN) return@OnTouchListener false var currentTouchTime = getAdditionalInstanceField(view, "currentTouchTime") as Long var currentTouchX = getAdditionalInstanceField(view, "currentTouchX") as Float var currentTouchY = getAdditionalInstanceField(view, "currentTouchY") as Float val lastTouchTime = currentTouchTime val lastTouchX = currentTouchX val lastTouchY = currentTouchY currentTouchTime = System.currentTimeMillis() currentTouchX = event.x currentTouchY = event.y if (currentTouchTime - lastTouchTime < 250L && kotlin.math.abs(currentTouchX - lastTouchX) < 100f && kotlin.math.abs(currentTouchY - lastTouchY) < 100f ) { val keyguardMgr = v.context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager if (keyguardMgr.isKeyguardLocked) { XposedHelpers.callMethod( v.context.getSystemService(Context.POWER_SERVICE), "goToSleep", SystemClock.uptimeMillis() ) } currentTouchTime = 0L currentTouchX = 0f currentTouchY = 0f } setAdditionalInstanceField(view, "currentTouchTime", currentTouchTime) setAdditionalInstanceField(view, "currentTouchX", currentTouchX) setAdditionalInstanceField(view, "currentTouchY", currentTouchY) v.performClick() false }) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/NoPassword.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object NoPassword : BaseHook() { override fun init() { loadClass("com.android.internal.widget.LockPatternUtils\$StrongAuthTracker").methodFinder().first { name == "isBiometricAllowedForUser" }.createHook { before { it.result = true } } loadClass("com.android.internal.widget.LockPatternUtils").methodFinder().first { name == "isBiometricAllowedForUser" }.createHook { before { it.result = true } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/RemoveCamera.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import android.view.View import android.widget.LinearLayout import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidU import com.sevtinge.cemiuiler.utils.getObjectField object RemoveCamera : BaseHook() { override fun init() { // 屏蔽右下角组件显示 loadClass( if (isAndroidU()) "com.android.keyguard.injector.KeyguardBottomAreaInjector" else "com.android.systemui.statusbar.phone.KeyguardBottomAreaView").methodFinder().first { name == "onFinishInflate" }.createHook { after { (it.thisObject.getObjectField("mRightAffordanceViewLayout") as LinearLayout).visibility = View.GONE } } // 屏蔽滑动撞墙动画 loadClass("com.android.keyguard.KeyguardMoveRightController").methodFinder().first { name == "onTouchMove" && parameterCount == 2 }.createHook { before { it.result = false } } loadClass("com.android.keyguard.KeyguardMoveRightController").methodFinder().first { name == "reset" }.createHook { before { it.result = null } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/RemoveSmartScreen.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object RemoveSmartScreen : BaseHook() { override fun init() { loadClass("com.android.keyguard.negative.MiuiKeyguardMoveLeftViewContainer").methodFinder().first { name == "inflateLeftView" }.createHook { before { it.result = null } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/lockscreen/ScramblePIN.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.lockscreen; import android.view.View; import android.view.ViewGroup; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.ArrayList; import java.util.Collections; import de.robv.android.xposed.XposedHelpers; public class ScramblePIN extends BaseHook { Class mKeyguardPINView; @Override public void init() { mKeyguardPINView = findClassIfExists("com.android.keyguard.KeyguardPINView"); findAndHookMethod(mKeyguardPINView, "onFinishInflate", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { View[][] mViews = (View[][]) XposedHelpers.getObjectField(param.thisObject, "mViews"); ArrayList mRandomViews = new ArrayList<>(); for (int row = 1; row <= 3; row++) { for (int col = 0; col <= 2; col++) { if (mViews[row][col] != null) mRandomViews.add(mViews[row][col]); } } mRandomViews.add(mViews[4][1]); Collections.shuffle(mRandomViews); View pinview = (View) param.thisObject; ViewGroup row1 = pinview.findViewById(pinview.getResources().getIdentifier("row1", "id", "com.android.systemui")); ViewGroup row2 = pinview.findViewById(pinview.getResources().getIdentifier("row2", "id", "com.android.systemui")); ViewGroup row3 = pinview.findViewById(pinview.getResources().getIdentifier("row3", "id", "com.android.systemui")); ViewGroup row4 = pinview.findViewById(pinview.getResources().getIdentifier("row4", "id", "com.android.systemui")); row1.removeAllViews(); row2.removeAllViews(); row3.removeAllViews(); row4.removeViewAt(1); mViews[1] = new View[]{mRandomViews.get(0), mRandomViews.get(1), mRandomViews.get(2)}; row1.addView(mRandomViews.get(0)); row1.addView(mRandomViews.get(1)); row1.addView(mRandomViews.get(2)); mViews[2] = new View[]{mRandomViews.get(3), mRandomViews.get(4), mRandomViews.get(5)}; row2.addView(mRandomViews.get(3)); row2.addView(mRandomViews.get(4)); row2.addView(mRandomViews.get(5)); mViews[3] = new View[]{mRandomViews.get(6), mRandomViews.get(7), mRandomViews.get(8)}; row3.addView(mRandomViews.get(6)); row3.addView(mRandomViews.get(7)); row3.addView(mRandomViews.get(8)); mViews[4] = new View[]{null, mRandomViews.get(9), mViews[4][2]}; row4.addView(mRandomViews.get(9), 1); XposedHelpers.setObjectField(param.thisObject, "mViews", mViews); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/navigation/HandleLineCustom.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.navigation import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam object HandleLineCustom : BaseHook() { override fun init() { val mNavigationHandleRadius = mPrefsMap.getInt("system_ui_navigation_handle_custom_thickness", 185).toFloat() / 100 try { mResHook.setDensityReplacement( "com.android.systemui", "dimen", "navigation_handle_radius", mNavigationHandleRadius ) } catch (e: Exception) { XposedLogUtils.logI(e.toString()) } /* val mNavigationHandleHeight = mPrefsMap.getInt("system_ui_navigation_handle_custom_thickness", 600).toFloat() / 10 val mNavigationHomeHandleWidth = mPrefsMap.getInt("system_ui_navigation_handle_custom_width", 145).toFloat() val mNavigationHomeHandleWidthLand = mPrefsMap.getInt("system_ui_navigation_handle_custom_width_land", 254).toFloat() try { mResHook.setDensityReplacement( "com.android.systemui", "dimen", "navigation_handle_bottom", mNavigationHandleHeight ); } catch (e: Exception) { log(e.toString()) } */ /* try { mResHook.setDensityReplacement("com.android.systemui", "dimen", "navigation_home_handle_width", 666.0f); } catch (Exception e) { log(String.valueOf(e)); } try { //写法1 //mResHook.setObjectReplacement("com.android.systemui", "dimen_land", "navigation_home_handle_width", mNavigationHomeHandleWidthLand); } catch (Exception e) { log(String.valueOf(e)); }*/ // 写法2 // mResHook.setDensityReplacement("com.android.systemui", "dimen_land", "navigation_home_handle_width", mNavigationHomeHandleWidthLand); // mResHook.setDensityReplacement("com.android.systemui", "dimen", "navigation_handle_horizontal_margin", 3); // mResHook.setDensityReplacement("com.android.systemui", "dimen", "navigation_handle_sample_horizontal_margin", 3); } fun initResource(resParam: InitPackageResourcesParam) { val mNavigationHandleLightColor = mPrefsMap.getInt("system_ui_navigation_handle_custom_color", -872415232) val mNavigationHandleDarkColor = mPrefsMap.getInt("system_ui_navigation_handle_custom_color_dark", -1) XposedLogUtils.logI("mNavigationHandleLightColor is $mNavigationHandleLightColor") XposedLogUtils.logI("mNavigationHandleDarkColor is $mNavigationHandleDarkColor") resParam.res.setReplacement( "com.android.systemui", "color", "navigation_bar_home_handle_dark_color", mNavigationHandleLightColor ) resParam.res.setReplacement( "com.android.systemui", "color", "navigation_bar_home_handle_light_color", mNavigationHandleDarkColor ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/navigation/NavigationCustom.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.navigation; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; public class NavigationCustom extends BaseHook { @Override public void init() { float mNavigationHeight = ((float) mPrefsMap.getInt("system_ui_navigation_custom_height", 100) / 10); float mNavigationHeightLand = ((float) mPrefsMap.getInt("system_ui_navigation_custom_height_land", 100) / 10); float mNavigationFrameHeight = ((float) mPrefsMap.getInt("system_ui_navigation_frame_custom_height", 100) / 10); float mNavigationFrameHeightLand = ((float) mPrefsMap.getInt("system_ui_navigation_frame_custom_height_land", 100) / 10); try { mResHook.setDensityReplacement("com.android.systemui", "dimen", "navigation_bar_height", mNavigationHeight); } catch (Exception e) { XposedLogUtils.logI(String.valueOf(e)); } try { mResHook.setDensityReplacement("com.android.systemui", "dimen", "navigation_bar_height_landscape", mNavigationHeightLand); } catch (Exception e) { XposedLogUtils.logI(String.valueOf(e)); } try { mResHook.setDensityReplacement("com.android.systemui", "dimen", "navigation_bar_frame_height", mNavigationFrameHeight); } catch (Exception e) { XposedLogUtils.logI(String.valueOf(e)); } try { mResHook.setDensityReplacement("com.android.systemui", "dimen", "navigation_bar_frame_height_landscape", mNavigationFrameHeightLand); } catch (Exception e) { XposedLogUtils.logI(String.valueOf(e)); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/plugin/EnableVolumeBlur.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.plugin; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class EnableVolumeBlur { public static void initEnableVolumeBlur(ClassLoader classLoader) { XposedHelpers.findAndHookMethod("com.android.systemui.miui.volume.Util", classLoader, "isSupportBlurS", XC_MethodReplacement.returnConstant(true)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/plugin/HideDeviceControlEntry.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.plugin; import static com.sevtinge.cemiuiler.module.base.BaseHook.mPrefsMap; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class HideDeviceControlEntry { public static void initHideDeviceControlEntry(ClassLoader classLoader) { if (mPrefsMap.getStringAsInt("system_ui_control_center_device_ctrl_entry", 0) == 1) { XposedHelpers.findAndHookMethod("miui.systemui.controlcenter.panel.main.external.DeviceControlEntryController", classLoader, "available", boolean.class, XC_MethodReplacement.returnConstant(true)); } else if (mPrefsMap.getStringAsInt("system_ui_control_center_device_ctrl_entry", 0) == 2) { XposedHelpers.findAndHookMethod("miui.systemui.controlcenter.panel.main.external.DeviceControlEntryController", classLoader, "available", boolean.class, XC_MethodReplacement.returnConstant(false)); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/plugin/HideMiPlayEntry.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.plugin; import static com.sevtinge.cemiuiler.module.base.BaseHook.mPrefsMap; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class HideMiPlayEntry { public static void initHideMiPlayEntry(ClassLoader classLoader) { if (mPrefsMap.getStringAsInt("system_ui_control_center_mi_play_entry", 0) == 1) { XposedHelpers.findAndHookMethod("miui.systemui.controlcenter.panel.main.external.MiPlayEntryController", classLoader, "available", boolean.class, XC_MethodReplacement.returnConstant(true)); } else if (mPrefsMap.getStringAsInt("system_ui_control_center_mi_play_entry", 0) == 2) { XposedHelpers.findAndHookMethod("miui.systemui.controlcenter.panel.main.external.MiPlayEntryController", classLoader, "available", boolean.class, XC_MethodReplacement.returnConstant(false)); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/plugin/HideMiSmartHubEntry.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.plugin; import static com.sevtinge.cemiuiler.module.base.BaseHook.mPrefsMap; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class HideMiSmartHubEntry { public static void initHideMiSmartHubEntry(ClassLoader classLoader) { if (mPrefsMap.getStringAsInt("system_ui_control_center_mi_smart_hub_entry", 0) == 1) { XposedHelpers.findAndHookMethod("miui.systemui.controlcenter.panel.main.external.MiSmartHubEntryController", classLoader, "available", boolean.class, XC_MethodReplacement.returnConstant(true)); } else if (mPrefsMap.getStringAsInt("system_ui_control_center_mi_smart_hub_entry", 0) == 2) { XposedHelpers.findAndHookMethod("miui.systemui.controlcenter.panel.main.external.MiSmartHubEntryController", classLoader, "available", boolean.class, XC_MethodReplacement.returnConstant(false)); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/plugin/PluginHelper.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.plugin; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidT; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidU; import android.content.pm.ApplicationInfo; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.module.hook.systemui.NotificationVolumeSeparateSlider; import com.sevtinge.cemiuiler.module.hook.systemui.controlcenter.BluetoothTileStyle; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; public class PluginHelper extends BaseHook { private static ClassLoader pluginLoader = null; private static ApplicationInfo appInfo = null; @Override public void init() { if (!isAndroidU()) { String pluginLoaderClass = isAndroidT() ? "com.android.systemui.shared.plugins.PluginInstance$Factory" : "com.android.systemui.shared.plugins.PluginManagerImpl"; hookAllMethods(pluginLoaderClass, "getClassLoader", new MethodHook() { private boolean isHooked = false; @Override protected void after(MethodHookParam param) { appInfo = (ApplicationInfo) param.args[0]; if (appInfo != null) { if ("miui.systemui.plugin".equals(appInfo.packageName) && !isHooked) { isHooked = true; if (pluginLoader == null) { pluginLoader = (ClassLoader) param.getResult(); } // XposedLogUtils.logD("pluginLoader: " + pluginLoader); setClassLoader(pluginLoader); } else { if (!isHooked) XposedLogUtils.logD("appInfo is not miui.systemui.plugin is: " + appInfo.packageName + " isHooked: " + isHooked); } } else { XposedLogUtils.logE(TAG, "appInfo is null"); } } } ); } else { hookAllMethods("com.android.systemui.shared.plugins.PluginInstance$Factory", "create", new MethodHook() { @Override protected void before(MethodHookParam param) { appInfo = (ApplicationInfo) param.args[1]; } } ); findAndHookMethod("com.android.systemui.shared.plugins.PluginInstance$Factory$$ExternalSyntheticLambda0", "get", new MethodHook() { private boolean isHooked = false; @Override protected void after(MethodHookParam param) { Object pathClassLoader = param.getResult(); if (appInfo != null) { if ("miui.systemui.plugin".equals(appInfo.packageName) && !isHooked) { isHooked = true; if (pluginLoader == null) { pluginLoader = (ClassLoader) pathClassLoader; } // XposedLogUtils.logD("AU pluginLoader: " + pluginLoader); setClassLoader(pluginLoader); } else { if (!isHooked) XposedLogUtils.logD("AU appInfo is not miui.systemui.plugin is: " + appInfo.packageName + " isHooked: " + isHooked); } } else { XposedLogUtils.logE(TAG, "AU appInfo is null"); } } } ); } } public void setClassLoader(ClassLoader classLoader) { if (mPrefsMap.getBoolean("system_ui_plugin_enable_volume_blur")) EnableVolumeBlur.initEnableVolumeBlur(classLoader); if (mPrefsMap.getStringAsInt("system_ui_control_center_mi_smart_hub_entry", 0) != 0) HideMiSmartHubEntry.initHideMiSmartHubEntry(classLoader); if (mPrefsMap.getStringAsInt("system_ui_control_center_mi_play_entry", 0) != 0) HideMiPlayEntry.initHideMiPlayEntry(classLoader); if (mPrefsMap.getStringAsInt("system_ui_control_center_device_ctrl_entry", 0) != 0) HideDeviceControlEntry.initHideDeviceControlEntry(classLoader); if (mPrefsMap.getStringAsInt("system_ui_control_center_cc_bluetooth_tile_style", 1) > 1) BluetoothTileStyle.initHideDeviceControlEntry(classLoader); if (mPrefsMap.getBoolean("system_framework_volume_separate_control") && mPrefsMap.getBoolean("system_framework_volume_separate_slider")) NotificationVolumeSeparateSlider.initHideDeviceControlEntry(classLoader); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/BigMobileNetworkType.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.graphics.Typeface; import android.util.TypedValue; import android.view.Gravity; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class BigMobileNetworkType extends BaseHook { @Override public void init() { /*MethodHook showSingleMobileType = new MethodHook(MethodHook.PRIORITY_HIGHEST) { @Override protected void before(MethodHookParam param) throws Throwable { Object mobileIconState = param.args[0]; XposedHelpers.setObjectField(mobileIconState, "showMobileDataTypeSingle", true); XposedHelpers.setObjectField(mobileIconState, "fiveGDrawableId", 0); } }; MethodHook afterUpdate = new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { Object mMobileLeftContainer = XposedHelpers.getObjectField(param.thisObject, "mMobileLeftContainer"); XposedHelpers.callMethod(mMobileLeftContainer, "setVisibility", 8); } }; hookAllMethods("com.android.systemui.statusbar.StatusBarMobileView", "applyMobileState", showSingleMobileType); hookAllMethods("com.android.systemui.statusbar.StatusBarMobileView", "applyMobileState", afterUpdate); */ } @SuppressLint("DiscouragedApi") private void old() { findAndHookMethod("com.android.systemui.statusbar.StatusBarMobileView", "init", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { ViewGroup mStatusBarMobileView = (ViewGroup) param.thisObject; Context mContext = mStatusBarMobileView.getContext(); Resources mRes = mContext.getResources(); // 获取组件 // mMobileLeftContainer int mobileContainerLeftId = mRes.getIdentifier("mobile_container_left", "id", "com.android.systemui"); // mMobileType int mobileTypeId = mRes.getIdentifier("mobile_type", "id", "com.android.systemui"); // mLeftInOut int mobileLeftMobileInoutId = mRes.getIdentifier( "mobile_left_mobile_inout", "id", "com.android.systemui"); ViewGroup mobileContainerLeft = mStatusBarMobileView.findViewById(mobileContainerLeftId); TextView mobileType = mStatusBarMobileView.findViewById(mobileTypeId); ImageView mobileLeftMobileInout = mStatusBarMobileView.findViewById(mobileLeftMobileInoutId); // 获取插入位置 // mMobileRightContainer int mobileContainerRightId = mRes.getIdentifier( "mobile_container_right", "id", "com.android.systemui" ); ViewGroup mobileContainerRight = mStatusBarMobileView.findViewById(mobileContainerRightId); ViewGroup rightParentLayout = (ViewGroup) mobileContainerRight.getParent(); int mobileContainerRightIndex = rightParentLayout.indexOfChild(mobileContainerRight); // 创建新布局 LinearLayout.LayoutParams newLinearLayoutLP = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT ); LinearLayout newLinearlayout = new LinearLayout(mContext); newLinearlayout.setLayoutParams(newLinearLayoutLP); newLinearlayout.setId(mobileContainerLeftId); newLinearlayout.setPadding(0, 0, 0, 0); XposedHelpers.setObjectField(param.thisObject, "mMobileLeftContainer", newLinearlayout); rightParentLayout.addView(newLinearlayout, mobileContainerRightIndex); // 将组件插入新的布局 ((ViewGroup) mobileType.getParent()).removeView(mobileType); ((ViewGroup) mobileLeftMobileInout.getParent()).removeView(mobileLeftMobileInout); ((ViewGroup) mobileContainerLeft.getParent()).removeView(mobileContainerLeft); // 类型 newLinearlayout.addView(mobileType); LinearLayout.LayoutParams mobileTypeLp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT ); mobileTypeLp.gravity = Gravity.CENTER_VERTICAL; mobileTypeLp.topMargin = 0; mobileType.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12.5f); boolean isBold = true; if (isBold) { mobileType.setTypeface(Typeface.DEFAULT_BOLD); } mobileType.setLayoutParams(mobileTypeLp); // 箭头 newLinearlayout.addView(mobileLeftMobileInout); LinearLayout.LayoutParams mobileLeftMobileInoutLp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT ); mobileLeftMobileInout.setLayoutParams(mobileLeftMobileInoutLp); // 屏蔽更新布局 findAndHookMethod("com.android.systemui.statusbar.StatusBarMobileView", "updateMobileTypeLayout", String.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.args[0] = null; } }); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/DisplayHardwareDetail.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar; import static de.robv.android.xposed.XposedHelpers.callMethod; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.graphics.Typeface; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.Locale; import java.util.Objects; import java.util.Properties; import de.robv.android.xposed.XposedHelpers; public class DisplayHardwareDetail extends BaseHook { boolean showDeviceTemp; boolean showBatteryDetail; boolean isTempAtRight; boolean isBatteryAtRight; /*boolean hasRightIcon = false; boolean hasLeftIcon = false;*/ Class mDependency; Class mChargeUtils; Class mIconManager; Class mNetworkSpeedView; Class mDarkIconDispatcher; Class mStatusBarIconHolder; Class mNetworkSpeedController; Class mMiuiCollapsedStatusBarFragment; int mStatusbarTextIconLayoutResId; static final ArrayList mBatteryDetailViews = new ArrayList<>(); private String getSlotNameByType(int mIconType) { String slotName = ""; if (mIconType == 91) { slotName = "battery_detail"; } else if (mIconType == 92) { slotName = "device_temp"; } return slotName; } static class TextIcon { public boolean atRight; public int iconType; public TextIcon(boolean mAtRight, int mIconType) { atRight = mAtRight; iconType = mIconType; } } static class TextIconInfo { public boolean iconShow; public int iconType; public String iconText; } @Override public void init() { showBatteryDetail = mPrefsMap.getBoolean("system_ui_statusbar_battery_enable"); // 电池相关 showDeviceTemp = mPrefsMap.getBoolean("system_ui_statusbar_temp_enable"); // 温度相关 isTempAtRight = mPrefsMap.getBoolean("system_ui_statusbar_temp_right_show"); isBatteryAtRight = mPrefsMap.getBoolean("system_ui_statusbar_battery_right_show"); mStatusbarTextIconLayoutResId = mResHook.addResource("statusbar_text_icon", R.layout.statusbar_text_icon); mDependency = findClassIfExists("com.android.systemui.Dependency"); mChargeUtils = showBatteryDetail ? findClassIfExists("com.android.keyguard.charge.ChargeUtils") : null; mIconManager = findClassIfExists("com.android.systemui.statusbar.phone.StatusBarIconController$IconManager"); mNetworkSpeedView = findClassIfExists("com.android.systemui.statusbar.views.NetworkSpeedView"); mDarkIconDispatcher = findClassIfExists("com.android.systemui.plugins.DarkIconDispatcher"); mStatusBarIconHolder = findClassIfExists("com.android.systemui.statusbar.phone.StatusBarIconHolder"); mNetworkSpeedController = findClassIfExists("com.android.systemui.statusbar.policy.NetworkSpeedController"); mMiuiCollapsedStatusBarFragment = findClassIfExists("com.android.systemui.statusbar.phone.MiuiCollapsedStatusBarFragment"); Class mFinalChargeUtils = mChargeUtils; ArrayList mTextIcons = new ArrayList<>(); if (showBatteryDetail) { mTextIcons.add(new TextIcon(isBatteryAtRight, 91)); } if (showDeviceTemp) { mTextIcons.add(new TextIcon(isTempAtRight, 92)); } boolean hasRightIcon = false; boolean hasLeftIcon = false; for (TextIcon ti : mTextIcons) { if (ti.atRight) { hasRightIcon = true; } else { hasLeftIcon = true; } } if (hasRightIcon) { findAndHookMethod("com.android.systemui.statusbar.phone.MiuiCollapsedStatusBarFragment", "initMiuiViewsOnViewCreated", View.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Object iconController = XposedHelpers.getObjectField(param.thisObject, "mStatusBarIconController"); for (TextIcon ti : mTextIcons) { if (ti.atRight) { int slotIndex = (int) callMethod(iconController, "getSlotIndex", getSlotNameByType(ti.iconType)); Object iconHolder = callMethod(iconController, "getIcon", slotIndex, 0); if (iconHolder == null) { iconHolder = XposedHelpers.newInstance(mStatusBarIconHolder); XposedHelpers.setObjectField(iconHolder, "mType", ti.iconType); callMethod(iconController, "setIcon", slotIndex, iconHolder); } } } } }); hookAllMethods(mIconManager, "addHolder", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { if (param.args.length != 4) return; Object iconHolder = param.args[3]; int type = (int) callMethod(iconHolder, "getType"); if (type == 91 || type == 92) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) callMethod(param.thisObject, "onCreateLayoutParams"); TextIcon createIcon = null; for (TextIcon ti : mTextIcons) { if (ti.iconType == type) { createIcon = ti; break; } } TextView batteryView = createBatteryDetailView(mContext, lp, createIcon); int i = (int) param.args[0]; ViewGroup mGroup = (ViewGroup) XposedHelpers.getObjectField(param.thisObject, "mGroup"); mGroup.addView(batteryView, i); mBatteryDetailViews.add(batteryView); param.setResult(batteryView); } } }); } if (hasLeftIcon) { findAndHookMethod(mMiuiCollapsedStatusBarFragment, "initMiuiViewsOnViewCreated", View.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Context mContext = (Context) callMethod(param.thisObject, "getContext"); Object DarkIconDispatcher = XposedHelpers.callStaticMethod(mDependency, "get", mDarkIconDispatcher); TextView mSplitter = (TextView) XposedHelpers.getObjectField(param.thisObject, "mDripNetworkSpeedSplitter"); ViewGroup batteryViewContainer = (ViewGroup) mSplitter.getParent(); int bvIndex = batteryViewContainer.indexOfChild(mSplitter); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSplitter.getLayoutParams(); for (TextIcon ti : mTextIcons) { if (!ti.atRight) { TextView batteryView = createBatteryDetailView(mContext, lp, ti); batteryViewContainer.addView(batteryView, bvIndex + 1); mBatteryDetailViews.add(batteryView); callMethod(DarkIconDispatcher, "addDarkReceiver", batteryView); XposedHelpers.setAdditionalInstanceField(param.thisObject, getSlotNameByType(ti.iconType), batteryView); } } } }); findAndHookMethod(mMiuiCollapsedStatusBarFragment, "showSystemIconArea", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { for (TextIcon ti : mTextIcons) { if (!ti.atRight) { Object bv = XposedHelpers.getAdditionalInstanceField(param.thisObject, getSlotNameByType(ti.iconType)); if (bv != null) { callMethod(bv, "setVisibilityByController", true); } } } } }); findAndHookMethod(mMiuiCollapsedStatusBarFragment, "hideSystemIconArea", boolean.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { for (TextIcon ti : mTextIcons) { if (!ti.atRight) { Object bv = XposedHelpers.getAdditionalInstanceField(param.thisObject, getSlotNameByType((ti.iconType))); if (bv != null) { callMethod(bv, "setVisibilityByController", false); } } } } }); } findAndHookMethod(mNetworkSpeedView, "getSlot", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Object customSlot = XposedHelpers.getAdditionalInstanceField(param.thisObject, "mCustomSlot"); if (customSlot != null) { param.setResult(customSlot); } } }); Helpers.hookAllConstructors("com.android.systemui.statusbar.policy.NetworkSpeedController", lpparam.classLoader, new Helpers.MethodHook() { Handler mBgHandler; @Override protected void after(MethodHookParam param) throws Throwable { Context mContext = (Context) param.args[0]; final Handler mHandler = new Handler(Looper.getMainLooper()) { public void handleMessage(Message message) { if (message.what == 100021) { TextIconInfo tii = (TextIconInfo) message.obj; String slotName = getSlotNameByType(tii.iconType); for (TextView tv : mBatteryDetailViews) { if (slotName.equals(XposedHelpers.getAdditionalInstanceField(tv, "mCustomSlot"))) { XposedHelpers.callMethod(tv, "setBlocked", !tii.iconShow); XposedHelpers.callMethod(tv, "setNetworkSpeed", tii.iconText); } } } } }; mBgHandler = new Handler((Looper) param.args[1]) { @SuppressLint("DefaultLocale") public void handleMessage(@NonNull Message message) { String subKey = ""; if (message.what == 200021) { String batteryInfo = ""; String deviceInfo = ""; boolean showBatteryInfo = showBatteryDetail; if (showBatteryInfo && mPrefsMap.getBoolean("system_ui_statusbar_battery_only_changing_show") && mFinalChargeUtils != null) { Object batteryStatus = Helpers.getStaticObjectFieldSilently(mFinalChargeUtils, "sBatteryStatus"); if (batteryStatus == null) { showBatteryInfo = false; } else { showBatteryInfo = (boolean) XposedHelpers.callMethod(batteryStatus, "isCharging"); } } if (showBatteryInfo || showDeviceTemp) { Properties props = null; String cpuProps = null; PowerManager powerMgr = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); boolean isScreenOn = powerMgr.isInteractive(); if (isScreenOn) { FileInputStream fis = null; RandomAccessFile cpuReader = null; try { fis = new FileInputStream("/sys/class/power_supply/battery/uevent"); props = new Properties(); props.load(fis); if (showDeviceTemp) { cpuReader = new RandomAccessFile("/sys/devices/virtual/thermal/thermal_zone0/temp", "r"); if (!Objects.equals(mPrefsMap.getString("system_ui_statusbar_temp_fix_cpu_get", "0"), "")) { try { cpuReader = new RandomAccessFile("/sys/devices/virtual/thermal/thermal_zone" + mPrefsMap.getString("system_ui_statusbar_temp_fix_cpu_get", "0") + "/temp", "r"); } catch (FileNotFoundException e) { XposedLogUtils.logI("get /sys/devices/virtual/thermal/thermal_zone*/temp (" + mPrefsMap.getString("system_ui_statusbar_temp_fix_cpu_get", "0") + ") failed: " + e); } } cpuProps = cpuReader.readLine(); } } catch (Throwable ignored) { } finally { try { if (fis != null) { fis.close(); } if (cpuReader != null) { cpuReader.close(); } } catch (Throwable ignored) { } } } if (showBatteryInfo && props != null) { String currVal; int rawCurr = 0; try { rawCurr = -1 * Math.round(Integer.parseInt(props.getProperty("POWER_SUPPLY_CURRENT_NOW")) / 1000f);// 概率fc } catch (NumberFormatException e) { XposedLogUtils.logI("get POWER_SUPPLY_CURRENT_NOW failed: " + e); } String preferred = "mA"; if (mPrefsMap.getBoolean("system_ui_statusbar_battery_electric_current")) { // 电流始终显示正值 rawCurr = Math.abs(rawCurr); } if (Math.abs(rawCurr) > 999) { currVal = String.format("%.2f", rawCurr / 1000f); preferred = "A"; } else { currVal = "" + rawCurr; } int opt = mPrefsMap.getStringAsInt("system_ui_statusbar_battery_show", 1); // 电池显示内容 int hideUnit = mPrefsMap.getStringAsInt("system_ui_statusbar_battery_disable", 0); String powerUnit = (hideUnit == 1 || hideUnit == 2) ? "" : "W"; String currUnit = (hideUnit == 1 || hideUnit == 3) ? "" : preferred; if (opt == 1) { float voltVal = 0f; String powerNow; try { powerNow = props.getProperty("POWER_SUPPLY_VOLTAGE_NOW"); } catch (Exception e) { throw new RuntimeException(e); } if (powerNow != null) voltVal = Integer.parseInt(powerNow) / 1000f / 1000f; String simpleWatt = String.format(Locale.getDefault(), "%.2f", Math.abs(voltVal * rawCurr) / 1000); String splitChar = mPrefsMap.getBoolean("system_ui_statusbar_battery_line_show") ? " " : "\n"; batteryInfo = simpleWatt + powerUnit + splitChar + currVal + currUnit; if (mPrefsMap.getBoolean("system_ui_statusbar_battery_opposite")) { batteryInfo = currVal + currUnit + splitChar + simpleWatt + powerUnit; } } else if (opt == 2) { float voltVal = 0f; String powerNow; try { powerNow = props.getProperty("POWER_SUPPLY_VOLTAGE_NOW"); } catch (Exception e) { throw new RuntimeException(e); } if (powerNow != null) voltVal = Integer.parseInt(powerNow) / 1000f / 1000f; String simpleWatt = String.format(Locale.getDefault(), "%.2f", Math.abs(voltVal * rawCurr) / 1000); batteryInfo = simpleWatt + powerUnit; } else { batteryInfo = currVal + currUnit; } } if (showDeviceTemp && props != null && cpuProps != null) { int batteryTempVal = 0; String powerTempNow; try { powerTempNow = props.getProperty("POWER_SUPPLY_TEMP"); } catch (Exception e) { throw new RuntimeException(e); } if (powerTempNow != null) batteryTempVal = Integer.parseInt(powerTempNow); int cpuTempVal = Integer.parseInt(cpuProps); boolean DecimalPlacesOr = mPrefsMap.getBoolean("system_ui_statusbar_temp_decimal_places"); String DecimalPlaces = DecimalPlacesOr ? "%.0f" : "%.1f"; String simpleBatteryTemp = String.format(Locale.getDefault(), DecimalPlaces, batteryTempVal / 10f); String simpleCpuTemp = String.format(Locale.getDefault(), DecimalPlaces, cpuTempVal / 1000f); int opt = mPrefsMap.getStringAsInt("system_ui_statusbar_temp_show", 1); boolean hideUnit = mPrefsMap.getBoolean("system_ui_statusbar_temp_disable"); String tempUnit = hideUnit ? "" : "℃"; if (opt == 1) { String splitChar = mPrefsMap.getBoolean("system_ui_statusbar_temp_line_show") ? " " : "\n"; deviceInfo = simpleBatteryTemp + tempUnit + splitChar + simpleCpuTemp + tempUnit; if (mPrefsMap.getBoolean("system_ui_statusbar_temp_opposite")) { deviceInfo = simpleCpuTemp + tempUnit + splitChar + simpleBatteryTemp + tempUnit; } } else if (opt == 2) { deviceInfo = simpleBatteryTemp + tempUnit; } else { deviceInfo = simpleCpuTemp + tempUnit; } } } if (showBatteryDetail) { TextIconInfo tii = new TextIconInfo(); tii.iconShow = showBatteryInfo; tii.iconText = batteryInfo; tii.iconType = 91; subKey = "battery"; mHandler.obtainMessage(100021, tii).sendToTarget(); } if (showDeviceTemp) { TextIconInfo tii = new TextIconInfo(); tii.iconShow = showDeviceTemp; tii.iconText = deviceInfo; tii.iconType = 92; subKey = "temp"; mHandler.obtainMessage(100021, tii).sendToTarget(); } } mBgHandler.removeMessages(200021); mBgHandler.sendEmptyMessageDelayed(200021, mPrefsMap.getInt("system_ui_statusbar_" + subKey + "_update_spacing", 2) * 1000L); } }; mBgHandler.sendEmptyMessage(200021); } }); } @SuppressLint("DiscouragedApi") private TextView createBatteryDetailView(Context mContext, LinearLayout.LayoutParams lp, TextIcon ti) { Resources res = mContext.getResources(); TextView batteryView = (TextView) LayoutInflater.from(mContext).inflate(res.getIdentifier("network_speed", "layout", "com.android.systemui"), (ViewGroup) null); batteryView.setTag("slot_text_icon"); batteryView.setVisibility(View.VISIBLE); XposedHelpers.setObjectField(batteryView, "mVisibilityByDisableInfo", 0); XposedHelpers.setObjectField(batteryView, "mVisibleByController", true); XposedHelpers.setObjectField(batteryView, "mShown", true); XposedHelpers.setAdditionalInstanceField(batteryView, "mCustomSlot", getSlotNameByType(ti.iconType)); int styleId = res.getIdentifier("TextAppearance.StatusBar.Clock", "style", "com.android.systemui"); batteryView.setTextAppearance(styleId); String subKey = ""; if (ti.iconType == 91) { subKey = "battery"; } else if (ti.iconType == 92) { subKey = "temp"; } float fontSize = mPrefsMap.getInt("system_ui_statusbar_" + subKey + "_size", 13); int opt = mPrefsMap.getStringAsInt("system_ui_statusbar_" + subKey + "_show", 1); if (!mPrefsMap.getBoolean("system_ui_statusbar_" + subKey + "_line_show") || mPrefsMap.getStringAsInt("system_ui_statusbar_" + subKey + "_show", 1) != 1) { fontSize = (float) (fontSize * 0.5); } XposedLogUtils.logI("fontsize = " + fontSize); int align = mPrefsMap.getStringAsInt("system_ui_status_bar_" + subKey + "_align", 1); int fixedWidth = mPrefsMap.getInt("system_ui_statusbar_" + subKey + "_fixedcontent_width", 10); int leftMargin = mPrefsMap.getInt("system_ui_statusbar_" + subKey + "_left_margin", 4); int rightMargin = mPrefsMap.getInt("system_ui_statusbar_" + subKey + "_right_margin", 4); int vertical = mPrefsMap.getInt("system_ui_statusbar_" + subKey + "_vertical_offset", 8); boolean isSingleRow = mPrefsMap.getBoolean("system_ui_statusbar_" + subKey + "_line_show"); boolean isFontBold = mPrefsMap.getBoolean("system_ui_statusbar_" + subKey + "_bold"); if (opt == 1 && !isSingleRow) { batteryView.setSingleLine(false); batteryView.setMaxLines(2); batteryView.setLineSpacing(0, fontSize > 8.5f ? 0.85f : 0.85f); } batteryView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSize); if (isFontBold) batteryView.setTypeface(Typeface.DEFAULT_BOLD); switch (align) { case 2 -> batteryView.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START); case 3 -> batteryView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); case 4 -> batteryView.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END); } if (fixedWidth > 10) lp.width = (int) (batteryView.getResources().getDisplayMetrics().density * fixedWidth); leftMargin = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, leftMargin, res.getDisplayMetrics() ); int topMargin = 0; if (vertical != 0) { float marginTop = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, (vertical - 8) * 0.5f, res.getDisplayMetrics() ); topMargin = (int) marginTop; } rightMargin = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, rightMargin, res.getDisplayMetrics() ); batteryView.setPaddingRelative(leftMargin, topMargin, rightMargin, 0); batteryView.setLayoutParams(lp); return batteryView; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/DoubleTapToSleep.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar import android.content.Context import android.os.SystemClock import android.view.MotionEvent import android.view.View import android.view.ViewGroup import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XposedHelpers import kotlin.math.abs object DoubleTapToSleep : BaseHook() { override fun init() { loadClass("com.android.systemui.statusbar.phone.MiuiPhoneStatusBarView").methodFinder().first { name == "onFinishInflate" }.createHook { before { val view = it.thisObject as ViewGroup XposedHelpers.setAdditionalInstanceField(view, "currentTouchTime", 0L) XposedHelpers.setAdditionalInstanceField(view, "currentTouchX", 0f) XposedHelpers.setAdditionalInstanceField(view, "currentTouchY", 0f) view.setOnTouchListener(View.OnTouchListener { v, event -> if (event.action != MotionEvent.ACTION_DOWN) return@OnTouchListener false var currentTouchTime = XposedHelpers.getAdditionalInstanceField(view, "currentTouchTime") as Long var currentTouchX = XposedHelpers.getAdditionalInstanceField(view, "currentTouchX") as Float var currentTouchY = XposedHelpers.getAdditionalInstanceField(view, "currentTouchY") as Float val lastTouchTime = currentTouchTime val lastTouchX = currentTouchX val lastTouchY = currentTouchY currentTouchTime = System.currentTimeMillis() currentTouchX = event.x currentTouchY = event.y if (currentTouchTime - lastTouchTime < 250L && abs(currentTouchX - lastTouchX) < 100f && abs( currentTouchY - lastTouchY ) < 100f ) { XposedHelpers.callMethod( v.context.getSystemService(Context.POWER_SERVICE), "goToSleep", SystemClock.uptimeMillis() ) currentTouchTime = 0L currentTouchX = 0f currentTouchY = 0f } XposedHelpers.setAdditionalInstanceField( view, "currentTouchTime", currentTouchTime ) XposedHelpers.setAdditionalInstanceField(view, "currentTouchX", currentTouchX) XposedHelpers.setAdditionalInstanceField(view, "currentTouchY", currentTouchY) v.performClick() false }) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/DualRowSignalHook.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.util.SparseIntArray; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import android.widget.LinearLayout; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; import java.util.HashMap; import java.util.List; import de.robv.android.xposed.XposedHelpers; public class DualRowSignalHook extends BaseHook { @Override public void init() { boolean mobileTypeSingle = mPrefsMap.getBoolean("system_ui_statusbar_mobile_type_enable"); // 移动网络类型单独显示 if (!mobileTypeSingle) { mResHook.setDensityReplacement("com.android.systemui", "dimen", "status_bar_mobile_type_half_to_top_distance", 3); mResHook.setDensityReplacement("com.android.systemui", "dimen", "status_bar_mobile_left_inout_over_strength", 0); mResHook.setDensityReplacement("com.android.systemui", "dimen", "status_bar_mobile_type_middle_to_strength_start", -0.4f); } HashMap dualSignalResMap = new HashMap(); String[] colorModeList = {"", "dark", "tint"}; // String[] iconStyles = {"", "thick", "theme"}; String selectedIconStyle = mPrefsMap.getString("system_ui_status_mobile_network_icon_style", ""); // 图标样式 Helpers.findAndHookMethod("com.android.systemui.SystemUIApplication", lpparam.classLoader, "onCreate", new MethodHook() { private boolean isHooked = false; @Override @SuppressLint("DiscouragedApi") protected void after(MethodHookParam param) throws Throwable { if (!isHooked) { isHooked = true; Context mContext = (Context) XposedHelpers.callMethod(param.thisObject, "getApplicationContext"); Resources modRes = Helpers.getModuleRes(mContext); for (int slot = 1; slot <= 2; slot++) { for (int lvl = 0; lvl <= 5; lvl++) { for (String colorMode : colorModeList) { if (!selectedIconStyle.equals("theme") || !colorMode.equals("tint")) { String dualIconResName = "statusbar_signal_" + slot + "_" + lvl + (!colorMode.equals("") ? ("_" + colorMode) : "") + (!selectedIconStyle.equals("") ? ("_" + selectedIconStyle) : ""); int iconResId = modRes.getIdentifier(dualIconResName, "drawable", Helpers.mAppModulePkg); dualSignalResMap.put(dualIconResName, mResHook.addResource(dualIconResName, iconResId)); } } } } } } }); SparseIntArray signalResToLevelMap = new SparseIntArray(); // 移动网络和WiFi网络都移动到左侧 boolean moveSignalLeft = (mPrefsMap.getBoolean("system_ui_status_bar_wifi_at_left") || mPrefsMap.getBoolean("system_ui_status_bar_mobile_network_at_left")); String ControllerImplName = moveSignalLeft ? "MiuiDripLeftStatusBarIconControllerImpl" : "StatusBarIconControllerImpl"; Helpers.hookAllMethods("com.android.systemui.statusbar.phone." + ControllerImplName, lpparam.classLoader, "setMobileIcons", new MethodHook() { private boolean isHooked = false; @Override @SuppressLint("DiscouragedApi") protected void before(MethodHookParam param) throws Throwable { if (!isHooked) { isHooked = true; Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); Resources res = mContext.getResources(); signalResToLevelMap.put(res.getIdentifier("stat_sys_signal_0", "drawable", lpparam.packageName), 0); signalResToLevelMap.put(res.getIdentifier("stat_sys_signal_1", "drawable", lpparam.packageName), 1); signalResToLevelMap.put(res.getIdentifier("stat_sys_signal_2", "drawable", lpparam.packageName), 2); signalResToLevelMap.put(res.getIdentifier("stat_sys_signal_3", "drawable", lpparam.packageName), 3); signalResToLevelMap.put(res.getIdentifier("stat_sys_signal_4", "drawable", lpparam.packageName), 4); signalResToLevelMap.put(res.getIdentifier("stat_sys_signal_5", "drawable", lpparam.packageName), 5); signalResToLevelMap.put(res.getIdentifier("stat_sys_signal_null", "drawable", lpparam.packageName), 6); } List iconStates = (List) param.args[1]; if (iconStates.size() == 2) { Object mainIconState = iconStates.get(0); Object subIconState = iconStates.get(1); boolean subDataConnected = (boolean) XposedHelpers.getObjectField(subIconState, "dataConnected"); XposedHelpers.setObjectField(subIconState, "visible", false); int mainSignalResId = (int) XposedHelpers.getObjectField(mainIconState, "strengthId"); int subSignalResId = (int) XposedHelpers.getObjectField(subIconState, "strengthId"); int mainLevel = signalResToLevelMap.get(mainSignalResId); int subLevel = signalResToLevelMap.get(subSignalResId); int level; if (subDataConnected) { level = subLevel * 10 + mainLevel; String[] syncFields = {"showName", "activityIn", "activityOut"}; for (String field : syncFields) { XposedHelpers.setObjectField(mainIconState, field, XposedHelpers.getObjectField(subIconState, field)); } XposedHelpers.setObjectField(mainIconState, "dataConnected", true); } else { level = mainLevel * 10 + subLevel; } XposedHelpers.setObjectField(mainIconState, "strengthId", level); param.args[1] = iconStates; } } }); MethodHook beforeUpdate = new MethodHook() { @Override protected void before(final MethodHookParam param) throws Throwable { Object mobileIconState = param.args[0]; boolean visible = (boolean) XposedHelpers.getObjectField(mobileIconState, "visible"); boolean airplane = (boolean) XposedHelpers.getObjectField(mobileIconState, "airplane"); int level = (int) XposedHelpers.getObjectField(mobileIconState, "strengthId"); if (!visible || airplane || level == 0 || level > 100) { XposedHelpers.setAdditionalInstanceField(param.thisObject, "subStrengthId", -1); } else { XposedHelpers.setAdditionalInstanceField(param.thisObject, "subStrengthId", level % 10); XposedHelpers.setObjectField(mobileIconState, "fiveGDrawableId", 0); } } }; MethodHook afterUpdate = new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { int subStrengthId = (int) XposedHelpers.getAdditionalInstanceField(param.thisObject, "subStrengthId"); if (subStrengthId < 0) return; Object mSmallHd = XposedHelpers.getObjectField(param.thisObject, "mSmallHd"); XposedHelpers.callMethod(mSmallHd, "setVisibility", 8); Object mSmallRoaming = XposedHelpers.getObjectField(param.thisObject, "mSmallRoaming"); XposedHelpers.callMethod(mSmallRoaming, "setVisibility", 0); } }; Helpers.hookAllMethods("com.android.systemui.statusbar.StatusBarMobileView", lpparam.classLoader, "applyMobileState", beforeUpdate); Helpers.hookAllMethods("com.android.systemui.statusbar.StatusBarMobileView", lpparam.classLoader, "applyMobileState", afterUpdate); MethodHook resetImageDrawable = new MethodHook() { @Override protected void before(final MethodHookParam param) throws Throwable { int subStrengthId = (int) XposedHelpers.getAdditionalInstanceField(param.thisObject, "subStrengthId"); if (subStrengthId < 0) return; if (subStrengthId == 6) subStrengthId = 0; Object mobileIconState = XposedHelpers.getObjectField(param.thisObject, "mState"); int level1 = (int) XposedHelpers.getObjectField(mobileIconState, "strengthId"); level1 = level1 / 10; if (level1 == 6) level1 = 0; boolean mLight = (boolean) XposedHelpers.getObjectField(param.thisObject, "mLight"); boolean mUseTint = (boolean) XposedHelpers.getObjectField(param.thisObject, "mUseTint"); Object mSmallRoaming = XposedHelpers.getObjectField(param.thisObject, "mSmallRoaming"); Object mMobile = XposedHelpers.getObjectField(param.thisObject, "mMobile"); String colorMode = ""; if (mUseTint && !selectedIconStyle.equals("theme")) { colorMode = "_tint"; } else if (!mLight) { colorMode = "_dark"; } String iconStyle = ""; if (!selectedIconStyle.equals("")) { iconStyle = "_" + selectedIconStyle; } String sim1IconId = "statusbar_signal_1_" + level1 + colorMode + iconStyle; String sim2IconId = "statusbar_signal_2_" + subStrengthId + colorMode + iconStyle; int sim1ResId = dualSignalResMap.get(sim1IconId); int sim2ResId = dualSignalResMap.get(sim2IconId); XposedHelpers.callMethod(mMobile, "setImageResource", sim1ResId); XposedHelpers.callMethod(mSmallRoaming, "setImageResource", sim2ResId); } }; Helpers.findAndHookMethod("com.android.systemui.statusbar.StatusBarMobileView", lpparam.classLoader, "applyDarknessInternal", resetImageDrawable); int rightMargin = mPrefsMap.getInt("system_ui_statusbar_mobile_network_icon_right_margin", 0); int leftMargin = mPrefsMap.getInt("system_ui_statusbar_mobile_network_icon_left_margin", 0); int iconScale = mPrefsMap.getInt("system_ui_statusbar_mobile_network_icon_size", 10); // 图标缩放 int verticalOffset = mPrefsMap.getInt("system_ui_statusbar_mobile_network_icon_vertical_offset", 8); if (rightMargin > 0 || leftMargin > 0 || iconScale != 10 || verticalOffset != 8) { Helpers.findAndHookMethod("com.android.systemui.statusbar.StatusBarMobileView", lpparam.classLoader, "init", new MethodHook() { @Override protected void after(final MethodHookParam param) throws Throwable { LinearLayout mobileView = (LinearLayout) param.thisObject; Context mContext = mobileView.getContext(); Resources res = mContext.getResources(); int rightSpacing = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, rightMargin * 0.5f, res.getDisplayMetrics() ); int leftSpacing = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, leftMargin * 0.5f, res.getDisplayMetrics() ); mobileView.setPadding(leftSpacing, 0, rightSpacing, 0); View mMobile = (View) XposedHelpers.getObjectField(param.thisObject, "mMobile"); if (verticalOffset != 8) { float marginTop = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, (verticalOffset - 8) * 0.5f, res.getDisplayMetrics() ); FrameLayout mobileIcon = (FrameLayout) mMobile.getParent(); mobileIcon.setTranslationY(marginTop); } if (iconScale != 10) { View mSmallRoaming = (View) XposedHelpers.getObjectField(param.thisObject, "mSmallRoaming"); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mMobile.getLayoutParams(); int mIconHeight = (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 20 * iconScale / 10f, res.getDisplayMetrics() ); if (layoutParams == null) { layoutParams = new FrameLayout.LayoutParams(-2, mIconHeight); } else { layoutParams.height = mIconHeight; } layoutParams.gravity = Gravity.CENTER; mMobile.setLayoutParams(layoutParams); mSmallRoaming.setLayoutParams(layoutParams); } } }); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/HideStatusBarBeforeScreenshot.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar; import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.Helpers; public class HideStatusBarBeforeScreenshot extends BaseHook { @Override public void init() { Helpers.findAndHookMethod("com.android.systemui.statusbar.phone.MiuiCollapsedStatusBarFragment", lpparam.classLoader, "initMiuiViewsOnViewCreated", View.class, new MethodHook() { @SuppressLint("UnspecifiedRegisterReceiverFlag") @Override protected void after(MethodHookParam param) throws Throwable { View view = (View) param.args[0]; BroadcastReceiver br = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if ("miui.intent.TAKE_SCREENSHOT".equals(intent.getAction())) { boolean finished = intent.getBooleanExtra("IsFinished", true); view.setVisibility(finished ? View.VISIBLE : View.INVISIBLE); } } }; view.getContext().registerReceiver(br, new IntentFilter("miui.intent.TAKE_SCREENSHOT")); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/MobileNetwork.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar; import android.view.View; import android.widget.TextView; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.XposedHelpers; public class MobileNetwork extends BaseHook { Class mStatusBarMobileView; Class mMobileIconState; Class mHDController; @Override public void init() { mStatusBarMobileView = findClassIfExists("com.android.systemui.statusbar.StatusBarMobileView"); mMobileIconState = findClassIfExists("com.android.systemui.statusbar.phone.StatusBarSignalPolicy$MobileIconState"); mHDController = findClassIfExists("com.android.systemui.statusbar.policy.HDController"); findAndHookMethod(mStatusBarMobileView, "initViewState", mMobileIconState, new MethodHook() { @Override protected void after(MethodHookParam param) { updateIconState(param, "mSmallHd", "system_ui_status_bar_icon_small_hd"); updateIconState(param, "mVolte", "system_ui_status_bar_icon_big_hd"); } }); findAndHookMethod(mStatusBarMobileView, "updateState", mMobileIconState, new MethodHook() { @Override protected void after(MethodHookParam param) { updateIconState(param, "mSmallHd", "system_ui_status_bar_icon_small_hd"); updateIconState(param, "mVolte", "system_ui_status_bar_icon_big_hd"); } }); hookAllMethods(mStatusBarMobileView, "applyMobileState", new MethodHook() { @Override protected void after(MethodHookParam param) { int qpt = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_mobile_network_type", 0); boolean singleMobileType = mPrefsMap.getBoolean("system_ui_statusbar_mobile_type_enable"); boolean hideIndicator = mPrefsMap.getBoolean("system_ui_status_bar_mobile_indicator"); View mMobileType = getMobileType(param, qpt, singleMobileType); // 隐藏移动网络活动指示器 View mLeftInOut = (View) XposedHelpers.getObjectField(param.thisObject, "mLeftInOut"); if (hideIndicator) { View mRightInOut = (View) XposedHelpers.getObjectField(param.thisObject, "mRightInOut"); mLeftInOut.setVisibility(View.GONE); mRightInOut.setVisibility(View.GONE); } if (mMobileType.getVisibility() == View.GONE && mLeftInOut.getVisibility() == View.GONE) { View mMobileLeftContainer = (View) XposedHelpers.getObjectField(param.thisObject, "mMobileLeftContainer"); mMobileLeftContainer.setVisibility(View.GONE); } } }); findAndHookMethod(mHDController, "update", new MethodHook() { @Override protected void before(MethodHookParam param) { int opt = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_new_hd", 0); if (opt > 0) { XposedHelpers.setBooleanField(param.thisObject, "mWifiAvailable", opt == 1 ? false : opt == 2); } } }); // 信号 /*hookAllMethods("com.android.systemui.statusbar.StatusBarMobileView", "applyMobileState", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.callMethod(param.thisObject, "setVisibility", View.GONE); } });*/ } private static View getMobileType(MethodHookParam param, int qpt, boolean singleMobileType) { View mMobileType = (View) XposedHelpers.getObjectField(param.thisObject, "mMobileType"); boolean dataConnected = (boolean) XposedHelpers.getObjectField(param.args[0], "dataConnected"); if (qpt > 0) { if (qpt == 1) { if (singleMobileType) { TextView mMobileTypeSingle = (TextView) XposedHelpers.getObjectField(param.thisObject, "mMobileTypeSingle"); mMobileTypeSingle.setVisibility(View.VISIBLE); } else { mMobileType.setVisibility(View.VISIBLE); } } if (qpt == 3 && !dataConnected) { if (singleMobileType) { TextView mMobileTypeSingle = (TextView) XposedHelpers.getObjectField(param.thisObject, "mMobileTypeSingle"); mMobileTypeSingle.setVisibility(View.GONE); } else { mMobileType.setVisibility(View.GONE); } } if (qpt == 2) { if (singleMobileType) { TextView mMobileTypeSingle = (TextView) XposedHelpers.getObjectField(param.thisObject, "mMobileTypeSingle"); mMobileTypeSingle.setVisibility(View.GONE); } else { mMobileType.setVisibility(View.GONE); } } } return mMobileType; } private void updateIconState(MethodHookParam param, String fieldName, String key) { boolean isMobileConnected = false; int opt = mPrefsMap.getStringAsInt(key, 0); if (opt != 0) { View view = (View) XposedHelpers.getObjectField(param.thisObject, fieldName); switch (opt) { case 1 -> view.setVisibility(View.VISIBLE); case 2 -> view.setVisibility(View.GONE); case 3 -> { view.setVisibility(View.GONE); isMobileConnected = (boolean) XposedHelpers.getObjectField(param.args[0], "dataConnected"); } } if (isMobileConnected) { view.setVisibility(View.VISIBLE); } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/NotificationIconColumns.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidR import com.sevtinge.cemiuiler.utils.devicesdk.isMoreAndroidVersion import com.sevtinge.cemiuiler.utils.setObjectField object NotificationIconColumns : BaseHook() { override fun init() { if (isAndroidR()) return val maxIconsNum = mPrefsMap.getInt("system_ui_status_bar_notification_icon_maximum", 3) val maxDotsNum = mPrefsMap.getInt("system_ui_status_bar_notification_dots_maximum", 3) loadClass("com.android.systemui.statusbar.phone.NotificationIconContainer").methodFinder() .filterByName("miuiShowNotificationIcons") .filterByParamCount(1) .first().createHook { replace { if (it.args[0] as Boolean) { it.thisObject.setObjectField("MAX_DOTS", maxDotsNum) it.thisObject.setObjectField("MAX_STATIC_ICONS", maxIconsNum) if (isMoreAndroidVersion(33)) { it.thisObject.setObjectField("MAX_ICONS_ON_LOCKSCREEN", maxIconsNum) } else { it.thisObject.setObjectField("MAX_VISIBLE_ICONS_ON_LOCK", maxIconsNum) } } else { it.thisObject.setObjectField("MAX_DOTS", 0) it.thisObject.setObjectField("MAX_STATIC_ICONS", 0) if (isMoreAndroidVersion(33)) { it.thisObject.setObjectField("MAX_ICONS_ON_LOCKSCREEN", 0) } else { it.thisObject.setObjectField("MAX_VISIBLE_ICONS_ON_LOCK", 0) } } it.thisObject.callMethod("updateState") } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/SelectiveHideIconForAlarmClock.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar; import android.app.AlarmManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; import android.os.Handler; import android.provider.Settings; import android.text.TextUtils; import android.text.format.DateFormat; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Locale; import java.util.Objects; import java.util.TimeZone; import de.robv.android.xposed.XposedHelpers; public class SelectiveHideIconForAlarmClock extends BaseHook { private boolean lastState = false; Class mMiuiPhoneStatusBarPolicy; @Override public void init() { mMiuiPhoneStatusBarPolicy = findClassIfExists("com.android.systemui.statusbar.phone.MiuiPhoneStatusBarPolicy"); hookAllConstructors(mMiuiPhoneStatusBarPolicy, new MethodHook() { @Override protected void after(MethodHookParam param) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); XposedHelpers.setAdditionalInstanceField(param.thisObject, "mNextAlarmTime", getNextMIUIAlarmTime(mContext)); ContentResolver resolver = mContext.getContentResolver(); ContentObserver alarmObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { if (selfChange) return; XposedHelpers.setAdditionalInstanceField(param.thisObject, "mNextAlarmTime", getNextMIUIAlarmTime(mContext)); updateAlarmVisibility(param.thisObject, lastState); } }; resolver.registerContentObserver(Settings.System.getUriFor("next_alarm_clock_formatted"), false, alarmObserver); IntentFilter filter = new IntentFilter(); filter.addAction("android.intent.action.TIME_TICK"); filter.addAction("android.intent.action.TIME_SET"); filter.addAction("android.intent.action.TIMEZONE_CHANGED"); filter.addAction("android.intent.action.LOCALE_CHANGED"); final Object thisObject = param.thisObject; mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { updateAlarmVisibility(thisObject, lastState); } }, filter); } }); findAndHookMethod("com.android.systemui.statusbar.phone.PhoneStatusBarPolicy", "updateAlarm", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { lastState = (boolean) XposedHelpers.getObjectField(param.thisObject, "mHasAlarm"); updateAlarmVisibility(param.thisObject, lastState); } }); findAndHookMethod(mMiuiPhoneStatusBarPolicy, "onMiuiAlarmChanged", new MethodHook() { @Override protected void before(MethodHookParam param) { lastState = (boolean) XposedHelpers.getObjectField(param.thisObject, "mHasAlarm"); updateAlarmVisibility(param.thisObject, lastState); param.setResult(null); } }); } private void updateAlarmVisibility(Object thisObject, boolean state) { try { Object mIconController = XposedHelpers.getObjectField(thisObject, "mIconController"); if (!state) { XposedHelpers.callMethod(mIconController, "setIconVisibility", "alarm_clock", false); return; } Context mContext = (Context) XposedHelpers.getObjectField(thisObject, "mContext"); long nowTime = java.lang.System.currentTimeMillis(); long nextTime; try { nextTime = (long) XposedHelpers.getAdditionalInstanceField(thisObject, "mNextAlarmTime"); } catch (Throwable t) { nextTime = getNextMIUIAlarmTime(mContext); } if (nextTime == 0) nextTime = getNextStockAlarmTime(mContext); long diffMSec = nextTime - nowTime; if (diffMSec < 0) diffMSec += 7 * 24 * 60 * 60 * 1000; float diffHours = (diffMSec - 59 * 1000) / (1000f * 60f * 60f); boolean vis = diffHours <= mPrefsMap.getInt("system_ui_status_bar_icon_alarm_clock_n", 0); XposedHelpers.callMethod(mIconController, "setIconVisibility", "alarm_clock", vis); mIconController = XposedHelpers.getObjectField(thisObject, "miuiDripLeftStatusBarIconController"); XposedHelpers.callMethod(mIconController, "setIconVisibility", "alarm_clock", vis); XposedLogUtils.logI("Now is " + diffHours + "min remain, show when " + vis + "min remain."); } catch (Throwable t) { XposedLogUtils.logI("updateAlarmVisibility failed by " + t); } } public long getNextMIUIAlarmTime(Context context) { String nextAlarm = Settings.System.getString(context.getContentResolver(), "next_alarm_clock_formatted"); long nextTime = 0; if (!TextUtils.isEmpty(nextAlarm)) try { TimeZone timeZone = TimeZone.getTimeZone("UTC"); SimpleDateFormat dateFormat = new SimpleDateFormat(DateFormat.getBestDateTimePattern(Locale.getDefault(), DateFormat.is24HourFormat(context) ? "EHm" : "Ehma"), Locale.getDefault()); dateFormat.setTimeZone(timeZone); long nextTimePart = Objects.requireNonNull(dateFormat.parse(nextAlarm)).getTime(); Calendar cal = Calendar.getInstance(timeZone); cal.setFirstDayOfWeek(Calendar.MONDAY); cal.setTimeInMillis(nextTimePart); int targetDay = cal.get(Calendar.DAY_OF_WEEK); int targetHour = cal.get(Calendar.HOUR_OF_DAY); int targetMinute = cal.get(Calendar.MINUTE); cal = Calendar.getInstance(); int diff = targetDay - cal.get(Calendar.DAY_OF_WEEK); if (diff < 0) diff += 7; cal.add(Calendar.DAY_OF_MONTH, diff); cal.set(Calendar.HOUR_OF_DAY, targetHour); cal.set(Calendar.MINUTE, targetMinute); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); nextTime = cal.getTimeInMillis(); } catch (Throwable t) { XposedLogUtils.logE(TAG, t); } return nextTime; } public long getNextStockAlarmTime(Context context) { AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); if (alarmMgr == null) return 0; AlarmManager.AlarmClockInfo aci = alarmMgr.getNextAlarmClock(); return aci == null ? 0 : aci.getTriggerTime(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/WifiStandard.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.XposedHelpers; public class WifiStandard extends BaseHook { Class mWifiView; Class mWifiIconState; @Override public void init() { mWifiView = findClassIfExists("com.android.systemui.statusbar.StatusBarWifiView"); mWifiIconState = findClassIfExists("com.android.systemui.statusbar.phone.StatusBarSignalPolicy$WifiIconState"); findAndHookMethod(mWifiView, "applyWifiState", mWifiIconState, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Object mWifiIconState = param.args[0]; int mWifiStandard = XposedHelpers.getIntField(mWifiIconState, "wifiStandard"); if (mWifiIconState != null) { int opt = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_wifi_standard", 0); if (opt == 1) { XposedHelpers.setBooleanField(mWifiIconState, "showWifiStandard", mWifiStandard != 0); } else if (opt == 2) { XposedHelpers.setBooleanField(mWifiIconState, "showWifiStandard", false); } } } }); } private void setWifiStandardIconState(MethodHookParam param) { int wifiStandard = XposedHelpers.getIntField(param.thisObject, "wifiStandard"); int key = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_wifi_standard", 0); if (key == 1) { XposedHelpers.setBooleanField(param.thisObject, "showWifiStandard", wifiStandard != 0); } else if (key == 2) { XposedHelpers.setBooleanField(param.thisObject, "showWifiStandard", false); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/clock/TimeCustomization.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.clock import android.annotation.SuppressLint import android.content.Context import android.os.Handler import android.provider.Settings import android.util.TypedValue import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.MemberExtensions.paramCount import com.github.kyuubiran.ezxhelper.finders.ConstructorFinder.`-Static`.constructorFinder import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.callMethod import com.sevtinge.cemiuiler.utils.devicesdk.getAndroidVersion import com.sevtinge.cemiuiler.utils.getObjectField import java.lang.reflect.Method import java.text.SimpleDateFormat import java.util.Calendar import java.util.Date import java.util.Timer import java.util.TimerTask object TimeCustomization : BaseHook() { // 预设模式 private val getMode = mPrefsMap.getStringAsInt("system_ui_statusbar_clock_mode", 0) private val getClockSize = mPrefsMap.getInt("system_ui_statusbar_clock_size", 0) private val getClockDoubleSize = mPrefsMap.getInt("system_ui_statusbar_clock_double_size", 0) private val isYear = mPrefsMap.getBoolean("system_ui_statusbar_clock_year") private val isMonth = mPrefsMap.getBoolean("system_ui_statusbar_clock_month") private val isDay = mPrefsMap.getBoolean("system_ui_statusbar_clock_date") private val isWeek = mPrefsMap.getBoolean("system_ui_statusbar_clock_week") private val isHideSpace = mPrefsMap.getBoolean("system_ui_statusbar_clock_hide_space") private val isDoubleLine = mPrefsMap.getBoolean("system_ui_statusbar_clock_double") private val isSecond = mPrefsMap.getBoolean("system_ui_statusbar_clock_second") private val isDoubleHour = mPrefsMap.getBoolean("system_ui_statusbar_clock_hour_cn") private val isPeriod = mPrefsMap.getBoolean("system_ui_statusbar_clock_period") // 极客模式 private val getGeekClockSize = mPrefsMap.getInt("system_ui_statusbar_clock_size_geek", 0) private val getGeekFormat = mPrefsMap.getString("system_ui_statusbar_clock_editor", "HH:mm:ss") private val mClockClass = when { getAndroidVersion() >= 31 -> loadClass("com.android.systemui.statusbar.views.MiuiClock") else -> loadClass("com.android.systemui.statusbar.policy.MiuiClock") } private lateinit var nowTime: Date private var str = "" @SuppressLint("SetTextI18n") override fun init() { when (getMode) { // 预设模式 1 -> { var c: Context? = null mClockClass!!.constructorFinder().first { paramCount == 3 }.createHook { after { try { c = it.args[0] as Context val textV = it.thisObject as TextView if (textV.resources.getResourceEntryName(textV.id) != "clock") return@after textV.isSingleLine = false if (isDoubleLine) { str = "\n" var clockDoubleLineSize = 7F if (getClockDoubleSize != 0) { clockDoubleLineSize = getClockDoubleSize.toFloat() } textV.setTextSize(TypedValue.COMPLEX_UNIT_DIP, clockDoubleLineSize) textV.setLineSpacing(0F, 0.8F) } else { if (getClockSize != 0) { val clockSize = getClockSize.toFloat() textV.setTextSize(TypedValue.COMPLEX_UNIT_DIP, clockSize) } } val d: Method = textV.javaClass.getDeclaredMethod("updateTime") val r = Runnable { d.isAccessible = true d.invoke(textV) } class T : TimerTask() { override fun run() { Handler(textV.context.mainLooper).post(r) } } Timer().scheduleAtFixedRate( T(), 1000 - System.currentTimeMillis() % 1000, 1000 ) } catch (_: Exception) { } } } mClockClass.methodFinder().first { name == "updateTime" }.createHook { after { try { val textV = it.thisObject as TextView if (textV.resources.getResourceEntryName(textV.id) == "clock") { val t = Settings.System.getString( c!!.contentResolver, Settings.System.TIME_12_24 ) val is24 = t == "24" nowTime = Calendar.getInstance().time textV.text = getDate(c!!) + str + getTime(c!!, is24) } } catch (_: Exception) { } } } } // 极客模式 2 -> { var c: Context? = null mClockClass!!.constructorFinder().first { paramCount == 3 }.createHook { after { try { c = it.args[0] as Context val textV = it.thisObject as TextView if (textV.resources.getResourceEntryName(textV.id) != "clock") return@after textV.isSingleLine = false textV.setLineSpacing(0F, 0.8F) if (getGeekClockSize != 0) { val clockSize = getGeekClockSize.toFloat() textV.setTextSize(TypedValue.COMPLEX_UNIT_DIP, clockSize) } val d: Method = textV.javaClass.getDeclaredMethod("updateTime") val r = Runnable { d.isAccessible = true d.invoke(textV) } class T : TimerTask() { override fun run() { Handler(textV.context.mainLooper).post(r) } } Timer().scheduleAtFixedRate( T(), 1000 - System.currentTimeMillis() % 1000, 1000 ) } catch (_: Exception) { } } } mClockClass.methodFinder().first { name == "updateTime" }.createHook { before { try { val textV = it.thisObject as TextView if (textV.resources.getResourceEntryName(textV.id) == "clock") { val mMiuiStatusBarClockController = textV.getObjectField("mMiuiStatusBarClockController") val mCalendar = mMiuiStatusBarClockController?.callMethod("getCalendar") mCalendar?.callMethod("setTimeInMillis", System.currentTimeMillis()) val textSb = StringBuilder() val formatSb = StringBuilder(getGeekFormat.toString()) mCalendar?.callMethod("format", c, textSb, formatSb) textV.text = textSb.toString() it.result = null } } catch (_: Exception) { } } } } } } @SuppressLint("SimpleDateFormat") private fun getDate(context: Context): String { var datePattern = "" val isZh = isZh(context) if (isYear) { if (isZh) { datePattern += "YY年" } else { datePattern += "YY" if (isMonth || isDay) datePattern += "/" } } if (isMonth) { if (isZh) { datePattern += "M月" } else { datePattern += "M" if (isDay) datePattern += "/" } } if (isDay) { datePattern += if (isZh) { "d日" } else { "d" } } if (isWeek) { if (!isHideSpace) datePattern = "$datePattern " datePattern += "E" if (!isDoubleLine) { if (!isHideSpace) datePattern = "$datePattern " } } datePattern = SimpleDateFormat(datePattern).format(nowTime) return datePattern } @SuppressLint("SimpleDateFormat") private fun getTime(context: Context, t: Boolean): String { var timePattern = "" val isZh = isZh(context) timePattern += if (t) "HH:mm" else "h:mm" if (isSecond) timePattern += ":ss" timePattern = SimpleDateFormat(timePattern).format(nowTime) if (isZh) timePattern = getPeriod(isZh) + timePattern else timePattern += getPeriod(isZh) timePattern = getDoubleHour() + timePattern return timePattern } @SuppressLint("SimpleDateFormat") private fun getPeriod(isZh: Boolean): String { var period = "" if (isPeriod) { if (isZh) { when (SimpleDateFormat("HH").format(nowTime)) { "00", "01", "02", "03", "04", "05" -> { period = "凌晨" } "06", "07", "08", "09", "10", "11" -> { period = "上午" } "12" -> { period = "中午" } "13", "14", "15", "16", "17" -> { period = "下午" } "18" -> { period = "傍晚" } "19", "20", "21", "22", "23" -> { period = "晚上" } } } else { period = SimpleDateFormat("a").format(nowTime) if (!isHideSpace) { period = " $period" } } } return period } @SuppressLint("SimpleDateFormat") private fun getDoubleHour(): String { var doubleHour = "" if (isDoubleHour) { when (SimpleDateFormat("HH").format(nowTime)) { "23", "00" -> { doubleHour = "子时" } "01", "02" -> { doubleHour = "丑时" } "03", "04" -> { doubleHour = "寅时" } "05", "06" -> { doubleHour = "卯时" } "07", "08" -> { doubleHour = "辰时" } "09", "10" -> { doubleHour = "巳时" } "11", "12" -> { doubleHour = "午时" } "13", "14" -> { doubleHour = "未时" } "15", "16" -> { doubleHour = "申时" } "17", "18" -> { doubleHour = "酉时" } "19", "20" -> { doubleHour = "戌时" } "21", "22" -> { doubleHour = "亥时" } } if (!isHideSpace) { doubleHour += " " } } return doubleHour } private fun isZh(context: Context): Boolean { return context.resources.configuration.locales.get(0).language.endsWith("zh") } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/clock/TimeStyle.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.clock import android.annotation.SuppressLint import android.content.res.Resources import android.graphics.Typeface import android.util.TypedValue import android.view.View import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.MemberExtensions.paramCount import com.github.kyuubiran.ezxhelper.finders.ConstructorFinder.`-Static`.constructorFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.getAndroidVersion object TimeStyle : BaseHook() { private val clockBold by lazy { mPrefsMap.getBoolean("system_ui_statusbar_clock_bold") } private val getMode by lazy { mPrefsMap.getStringAsInt("system_ui_statusbar_clock_mode", 0) } private val isAlign by lazy { mPrefsMap.getStringAsInt("system_ui_statusbar_clock_double_mode", 0) } private val isGeekAlign by lazy { mPrefsMap.getStringAsInt("system_ui_statusbar_clock_double_mode_geek", 0) } private val verticalOffset by lazy { mPrefsMap.getInt("system_ui_statusbar_clock_vertical_offset", 12) } private val mClockClass = when { getAndroidVersion() >= 31 -> loadClass("com.android.systemui.statusbar.views.MiuiClock") else -> loadClass("com.android.systemui.statusbar.policy.MiuiClock") } @SuppressLint("RtlHardcoded", "DiscouragedApi") override fun init() { mClockClass.constructorFinder().first { paramCount == 3 }.createHook { after { val textV = it.thisObject as TextView val res: Resources = textV.resources if (textV.resources.getResourceEntryName(textV.id) == "clock") { // 时钟加粗 if (clockBold) { textV.typeface = Typeface.DEFAULT_BOLD } // 时钟对齐方式 when (getMode) { // 预设模式下 1 -> { textV.textAlignment = when (isAlign) { 1 -> View.TEXT_ALIGNMENT_CENTER 2 -> View.TEXT_ALIGNMENT_TEXT_END else -> View.TEXT_ALIGNMENT_TEXT_START } } // 极客模式下 2 -> { textV.textAlignment = when (isGeekAlign) { 1 -> View.TEXT_ALIGNMENT_CENTER 2 -> View.TEXT_ALIGNMENT_TEXT_END else -> View.TEXT_ALIGNMENT_TEXT_START } } } } // 时钟边距调整 if (verticalOffset != 12) { val marginTop = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, (verticalOffset - 12) * 0.5f, res.displayMetrics ) textV.translationY = marginTop } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/BatteryStyle.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all import android.annotation.SuppressLint import android.graphics.Typeface import android.util.TypedValue import android.widget.LinearLayout import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.getAndroidVersion import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidR import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers @SuppressLint("StaticFieldLeak") object BatteryStyle : BaseHook() { private val verticalOffsetMark by lazy { mPrefsMap.getInt("system_ui_status_bar_battery_style_vertical_offset_mark", 27) } private val mBatteryMeterViewClass = when { getAndroidVersion() >= 31 -> loadClass("com.android.systemui.statusbar.views.MiuiBatteryMeterView") else -> loadClass("com.android.systemui.MiuiBatteryMeterView") } private lateinit var batteryView: LinearLayout private lateinit var mBatteryPercentView: TextView private lateinit var mBatteryPercentMarkView: TextView override fun init() { if (isAndroidR()) { mBatteryMeterViewClass.methodFinder().first { name == "updateResources" } } else { mBatteryMeterViewClass.methodFinder().first { name == "updateAll" } }.createHook { after { param -> batteryView = param.thisObject as LinearLayout mBatteryPercentView = XposedHelpers.getObjectField(param.thisObject, "mBatteryPercentView") as TextView mBatteryPercentMarkView = XposedHelpers.getObjectField(param.thisObject, "mBatteryPercentMarkView") as TextView // 交换电池图标与电量位置(电量外显下才能正常交换) if (mPrefsMap.getBoolean("system_ui_status_bar_battery_style_change_location")) { batteryView.removeView(mBatteryPercentView) batteryView.removeView(mBatteryPercentMarkView) batteryView.addView(mBatteryPercentMarkView, 0) batteryView.addView(mBatteryPercentView, 0) } // 自定义部分 enableCustom(param) } } } private fun enableCustom(param: XC_MethodHook.MethodHookParam) { val res = batteryView.resources val mBatteryTextDigitView = XposedHelpers.getObjectField(param.thisObject, "mBatteryTextDigitView") as TextView if (!mPrefsMap.getBoolean("system_ui_status_bar_battery_style_enable_custom")) return try { val fontSize = mPrefsMap.getInt("system_ui_status_bar_battery_style_font_size", 15) * 0.5f if (fontSize > 7.5) { mBatteryTextDigitView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSize) mBatteryPercentView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSize) } val fontSizeMark = mPrefsMap.getInt("system_ui_status_bar_battery_style_font_mark_size", 15) * 0.5f if (fontSizeMark > 7.5) { mBatteryPercentMarkView.setTextSize( TypedValue.COMPLEX_UNIT_DIP, fontSizeMark ) } if (mPrefsMap.getBoolean("system_ui_status_bar_battery_style_bold")) { mBatteryTextDigitView.typeface = Typeface.DEFAULT_BOLD mBatteryPercentView.typeface = Typeface.DEFAULT_BOLD } var leftMargin: Int = mPrefsMap.getInt("system_ui_status_bar_battery_style_left_margin", 0) var rightMargin: Int = mPrefsMap.getInt("system_ui_status_bar_battery_style_right_margin", 0) leftMargin = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, leftMargin * 0.5f, res.displayMetrics ).toInt() rightMargin = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, rightMargin * 0.5f, res.displayMetrics ).toInt() var topMargin = 0 val verticalOffset: Int = mPrefsMap.getInt("system_ui_status_bar_battery_style_vertical_offset", 8) if (verticalOffset != 12) { val marginTop = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, (verticalOffset - 12) * 0.5f, res.displayMetrics ) topMargin = marginTop.toInt() } var digitRightMargin = 0 var markRightMargin = 0 if (mPrefsMap.getBoolean("system_ui_status_bar_battery_percent_mark")) { digitRightMargin = rightMargin } else { markRightMargin = rightMargin } if (leftMargin > 0 || topMargin != 8 || digitRightMargin > 0) { mBatteryPercentView.setPaddingRelative( leftMargin, topMargin, digitRightMargin, 0 ) } if (verticalOffsetMark < 27) { val marginTop = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, (verticalOffsetMark - 8) * 0.5f, res.displayMetrics ) topMargin = marginTop.toInt() } if (verticalOffsetMark < 27 || markRightMargin > 0) { mBatteryPercentMarkView.setPaddingRelative(0, topMargin, markRightMargin, 0) } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/BluetoothIcon.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidU; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class BluetoothIcon extends BaseHook { @Override public void init() { hookAllMethods("com.android.systemui.statusbar.phone.MiuiPhoneStatusBarPolicy", "updateBluetooth", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { int opt = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_bluetooth", 0); int opt_b = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_bluetooth_battery", 0); boolean isBluetoothConnected; if (isAndroidU()) { isBluetoothConnected = (int) XposedHelpers.getObjectField(XposedHelpers.getObjectField(param.thisObject, "mBluetooth"), "mConnectionState") == 2; } else { isBluetoothConnected = (boolean) XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "mBluetooth"), "isBluetoothConnected"); } Object mIconController = XposedHelpers.getObjectField(param.thisObject, "mIconController"); if (opt == 2 || (opt == 3 && !isBluetoothConnected)) { XposedHelpers.callMethod(mIconController, "setIconVisibility", "bluetooth", false); } else if (opt == 1) { XposedHelpers.callMethod(mIconController, "setIconVisibility", "bluetooth", true); } if (opt_b == 2 || (opt_b == 3 && !isBluetoothConnected)) { XposedHelpers.callMethod(mIconController, "setIconVisibility", "bluetooth_handsfree_battery", false); } else if (opt_b == 1) { XposedHelpers.callMethod(mIconController, "setIconVisibility", "bluetooth_handsfree_battery", true); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/DataSaverIcon.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all; import com.sevtinge.cemiuiler.module.base.BaseHook; public class DataSaverIcon extends BaseHook { @Override public void init() { findAndHookMethod("com.android.systemui.statusbar.phone.PhoneStatusBarPolicy", "onDataSaverChanged", boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) { int opt = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_data_saver", 0); if (opt == 1) { param.args[0] = true; } else if (opt == 2) { param.args[0] = false; } } } ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/HideBatteryIcon.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all import android.view.View import android.widget.FrameLayout import android.widget.ImageView import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidR import com.sevtinge.cemiuiler.utils.devicesdk.isMoreAndroidVersion import com.sevtinge.cemiuiler.utils.getObjectField import com.sevtinge.cemiuiler.utils.getObjectFieldAs object HideBatteryIcon : BaseHook() { override fun init() { val mBatteryMeterViewClass = when { isAndroidR() -> loadClass("com.android.systemui.MiuiBatteryMeterView") isMoreAndroidVersion(31) -> loadClass("com.android.systemui.statusbar.views.MiuiBatteryMeterView") else -> null } mBatteryMeterViewClass!!.methodFinder().first { name == "updateResources" }.createHook { after { param -> // 隐藏电池图标 if (mPrefsMap.getBoolean("system_ui_status_bar_battery_icon")) { (param.thisObject?.getObjectFieldAs("mBatteryIconView"))?.visibility = View.GONE if (param.thisObject?.getObjectField("mBatteryStyle") == 1) { (param.thisObject?.getObjectFieldAs("mBatteryDigitalView"))?.visibility = View.GONE } } // 隐藏电池百分号 if (mPrefsMap.getBoolean("system_ui_status_bar_battery_percent") || mPrefsMap.getBoolean("system_ui_status_bar_battery_percent_mark") ) { (param.thisObject?.getObjectFieldAs("mBatteryPercentMarkView"))?.textSize = 0F } // 隐藏电池内的百分比 if (mPrefsMap.getBoolean("system_ui_status_bar_battery_percent")) { (param.thisObject?.getObjectFieldAs("mBatteryPercentView"))?.textSize = 0F (param.thisObject?.getObjectFieldAs("mBatteryTextDigitView"))?.textSize = 0F } } } mBatteryMeterViewClass.methodFinder().first { name == "updateChargeAndText" }.createHook { after { param -> // 隐藏电池充电图标 if (mPrefsMap.getBoolean("system_ui_status_bar_battery_charging")) { (param.thisObject?.getObjectFieldAs("mBatteryChargingInView"))?.visibility = View.GONE (param.thisObject?.getObjectFieldAs("mBatteryChargingView"))?.visibility = View.GONE } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/HideVoWiFiIcon.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object HideVoWiFiIcon : BaseHook() { override fun init() { loadClass("com.android.systemui.MiuiOperatorCustomizedPolicy\$MiuiOperatorConfig").methodFinder().first { name == "getHideVowifi" }.createHook { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/IconsFromSystemManager.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers import de.robv.android.xposed.XposedHelpers class IconsFromSystemManager : BaseHook() { override fun init() { Helpers.findAndHookMethod("com.android.systemui.statusbar.phone.StatusBarIconControllerImpl", lpparam.classLoader, "setIcon", String::class.java, "com.android.internal.statusbar.StatusBarIcon", object : MethodHook() { override fun before(param: MethodHookParam) { val slotName = param.args[0] as String val stealth = slotName == "stealth" && mPrefsMap.getBoolean("system_ui_status_bar_hide_icon_stealth") val mute = slotName == "mute" && mPrefsMap.getBoolean("system_ui_status_bar_hide_icon_mute") val speakerphone = slotName == "speakerphone" && mPrefsMap.getBoolean("system_ui_status_bar_hide_icon_speakerphone") val call_record = slotName == "call_record" && mPrefsMap.getBoolean("system_ui_status_bar_hide_icon_call_record") if (stealth || mute || speakerphone || call_record) { XposedHelpers.setObjectField(param.args[1], "visible", false) } } } ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/StatusBarIcon.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.MemberExtensions.paramCount import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidU class StatusBarIcon : BaseHook() { override fun init() { loadClass("com.android.systemui.statusbar.phone.StatusBarIconControllerImpl").methodFinder().first { name == "setIconVisibility" && paramCount == 2 }.createHook { before { param -> val iconType = param.args[0] as String when (checkSlot(iconType)) { 1 -> param.args[1] = true 2 -> param.args[1] = false } } } loadClass(if (isAndroidU()) "com.android.systemui.statusbar.phone.StatusBarIconControllerImpl" else "com.android.systemui.statusbar.phone.MiuiDripLeftStatusBarIconControllerImpl").methodFinder().first { name == "setIconVisibility" && paramCount == 2 }.createHook { before { param -> val iconType = param.args[0] as String when (checkSlot(iconType)) { 1 -> param.args[1] = true 2 -> param.args[1] = false } } } } companion object { private fun checkSlot(slotName: String): Int { val vpn = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_vpn", 0) val alarmClock = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_alarm_clock", 0) val nfc = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_nfc", 0) val zen = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_zen", 0) val volume = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_volume", 0) val wifi = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_wifi", 0) val wifi_slave = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_wifi_slave", 0) val airplane = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_airplane", 0) val location = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_location", 0) val hotspot = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_hotspot", 0) val headset = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_headset", 0) return when (slotName) { "vpn" -> // vpn if (isEnable(vpn)) vpn else 0 "alarm_clock" -> // 闹钟 if (isEnable(alarmClock)) alarmClock else 0 "nfc" -> // nfc if (isEnable(nfc)) nfc else 0 "zen" -> // 勿扰模式 if (isEnable(zen)) zen else 0 "volume" -> // 声音 if (isEnable(volume)) volume else 0 "wifi" -> // wifi if (isEnable(wifi)) wifi else 0 "wifi_slave" -> // 辅助wifi if (isEnable(wifi_slave)) wifi_slave else 0 "airplane" -> // 飞行模式 if (isEnable(airplane)) airplane else 0 "location" -> // 位置信息 if (isEnable(location)) location else 0 "hotspot" -> // 热点 if (isEnable(hotspot)) hotspot else 0 "headset" -> // 耳机 if (isEnable(headset)) headset else 0 else -> 0 } } private fun isEnable(i: Int): Boolean { return i in 1..2 } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/StatusBarIconPositionAdjust.java ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import de.robv.android.xposed.XposedHelpers; public class StatusBarIconPositionAdjust extends BaseHook { boolean isMoveLeft; boolean isMoveCenter; boolean isMoveRight; String[] mSignalIcons; ArrayList mSignalRelatedIcons; Class mStatusBarIconList; Class mSystemUIApplication; Class mMiuiDripLeftStatusBarIconControllerImpl; boolean isWiFiAtLeftEnable; boolean isMobileNetworkAtLeftEnable; boolean isSwapWiFiAndMobileNetwork; boolean isNetworkSpeedAtRightEnable; boolean isAlarmClockAtRightEnable; boolean isNFCAtRightEnable; boolean isVolmeAtRightEnable; boolean isZenAtRightEnable; boolean isHeadsetAtRightEnable; @Override public void init() { mStatusBarIconList = findClassIfExists("com.android.systemui.statusbar.phone.StatusBarIconList"); mSystemUIApplication = findClassIfExists("com.android.systemui.SystemUIApplication"); mMiuiDripLeftStatusBarIconControllerImpl = findClassIfExists("com.android.systemui.statusbar.phone.MiuiDripLeftStatusBarIconControllerImpl"); ArrayList dripLeftIcons = new ArrayList<>(); isWiFiAtLeftEnable = mPrefsMap.getBoolean("system_ui_status_bar_wifi_at_left"); isMobileNetworkAtLeftEnable = mPrefsMap.getBoolean("system_ui_status_bar_mobile_network_at_left"); isNetworkSpeedAtRightEnable = mPrefsMap.getBoolean("system_ui_status_bar_network_speed_at_right"); isAlarmClockAtRightEnable = mPrefsMap.getBoolean("system_ui_status_bar_alarm_clock_at_right"); isNFCAtRightEnable = mPrefsMap.getBoolean("system_ui_status_bar_nfc_at_right"); isVolmeAtRightEnable = mPrefsMap.getBoolean("system_ui_status_bar_volume_at_right"); isZenAtRightEnable = mPrefsMap.getBoolean("system_ui_status_bar_zen_at_right"); isHeadsetAtRightEnable = mPrefsMap.getBoolean("system_ui_status_bar_headset_at_right"); isSwapWiFiAndMobileNetwork = mPrefsMap.getBoolean("system_ui_status_bar_swap_wifi_and_mobile_network"); isMoveLeft = isWiFiAtLeftEnable || isMobileNetworkAtLeftEnable; isMoveRight = isNetworkSpeedAtRightEnable || isAlarmClockAtRightEnable || isNFCAtRightEnable || isVolmeAtRightEnable || isZenAtRightEnable || isHeadsetAtRightEnable; if (isWiFiAtLeftEnable && isMobileNetworkAtLeftEnable && !isSwapWiFiAndMobileNetwork) { mSignalIcons = new String[]{"no_sim", "mobile", "demo_mobile", "airplane", "hotspot", "slave_wifi", "wifi", "demo_wifi"}; } else { mSignalIcons = new String[]{"hotspot", "slave_wifi", "wifi", "demo_wifi", "no_sim", "mobile", "demo_mobile", "airplane"}; /*if (isWiFiAtLeftEnable) { mSignalIcons = new String[]{"hotspot", "slave_wifi", "wifi", "demo_wifi"}; } if (isMobileNetworkAtLeftEnable) { mSignalIcons = new String[]{"no_sim", "mobile", "demo_mobile", "airplane"}; }*/ } mSignalRelatedIcons = new ArrayList<>(Arrays.asList(mSignalIcons)); if (isMoveRight) { findAndHookMethod(mMiuiDripLeftStatusBarIconControllerImpl, "setIconVisibility", String.class, boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) { String slot = (String) param.args[0]; boolean isAlarmClockIcon = "alarm_clock".equals(slot) && isAlarmClockAtRightEnable; boolean isNFCIcon = "nfc".equals(slot) && isNFCAtRightEnable; boolean isVolumeIcon = "volume".equals(slot) && isVolmeAtRightEnable; boolean isZenIcon = "zen".equals(slot) && isZenAtRightEnable; boolean isHeadsetIcon = "headset".equals(slot) && isHeadsetAtRightEnable; if (isAlarmClockIcon || isNFCIcon || isVolumeIcon || isZenIcon || isHeadsetIcon) { param.args[1] = false; } } }); findAndHookMethod(mSystemUIApplication, "onCreate", new MethodHook() { @Override protected void after(MethodHookParam param) { ArrayList rightBlockList; Context mContext = (Context) XposedHelpers.callMethod(param.thisObject, "getApplicationContext"); Class MiuiEndIconManager = findClass("com.android.systemui.statusbar.phone.MiuiEndIconManager", lpparam.classLoader); Object blockList = getStaticObjectFieldSilently(MiuiEndIconManager, "RIGHT_BLOCK_LIST"); Resources res = mContext.getResources(); if (blockList != null) { rightBlockList = (ArrayList) blockList; } else { @SuppressLint("DiscouragedApi") int blockResId = res.getIdentifier("config_drip_right_block_statusBarIcons", "array", lpparam.packageName); rightBlockList = new ArrayList<>(Arrays.asList(res.getStringArray(blockResId))); } if (isNetworkSpeedAtRightEnable) { rightBlockList.remove("network_speed"); } if (isAlarmClockAtRightEnable) { rightBlockList.remove("alarm_clock"); } if (isVolmeAtRightEnable) { rightBlockList.remove("volume"); } if (isZenAtRightEnable) { rightBlockList.remove("zen"); } /*if (mPrefsMap.getBoolean("system_statusbar_btbattery_atright")) { rightBlockList.remove("bluetooth_handsfree_battery"); }*/ if (isNFCAtRightEnable) { rightBlockList.remove("nfc"); } if (isHeadsetAtRightEnable) { rightBlockList.remove("headset"); } if (blockList != null) { XposedHelpers.setStaticObjectField(MiuiEndIconManager, "RIGHT_BLOCK_LIST", rightBlockList); } else { mResHook.setObjectReplacement(lpparam.packageName, "array", "config_drip_right_block_statusBarIcons", rightBlockList.toArray(new String[0])); } } }); } if (isMoveLeft || isSwapWiFiAndMobileNetwork) { findAndHookConstructor(mStatusBarIconList, String[].class, new MethodHook() { @Override protected void before(MethodHookParam param) { boolean isRightController = "StatusBarIconControllerImpl".equals(param.thisObject.getClass().getSimpleName()); ArrayList allStatusIcons = new ArrayList<>(Arrays.asList((String[]) param.args[0])); if (isRightController) { int startIndex = allStatusIcons.indexOf("no_sim"); int endIndex = allStatusIcons.indexOf("demo_wifi") + 1; List removedIcons = allStatusIcons.subList(startIndex, endIndex); removedIcons.clear(); if (!isMoveLeft) { startIndex = allStatusIcons.indexOf("ethernet"); allStatusIcons.addAll(startIndex + 1, mSignalRelatedIcons); } param.args[0] = allStatusIcons.toArray(new String[0]); } else if (isMoveLeft && !isSwapWiFiAndMobileNetwork) { dripLeftIcons.addAll(allStatusIcons); allStatusIcons.addAll(0, mSignalRelatedIcons); param.args[0] = allStatusIcons.toArray(new String[0]); } } }); } if (isMoveLeft) { findAndHookMethod("com.android.systemui.statusbar.phone.MiuiStatusBarSignalPolicy", "initMiuiSlot", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { Object dripLeftController = XposedHelpers.callStaticMethod(findClass("com.android.systemui.Dependency", lpparam.classLoader), "get", findClass("com.android.systemui.statusbar.phone.MiuiDripLeftStatusBarIconControllerImpl", lpparam.classLoader)); XposedHelpers.setObjectField(param.thisObject, "mIconController", dripLeftController); } }); findAndHookMethod("com.android.systemui.statusbar.phone.MiuiCollapsedStatusBarFragment", "initMiuiViewsOnViewCreated", View.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Object dripLeftController = XposedHelpers.callStaticMethod(findClass("com.android.systemui.Dependency", lpparam.classLoader), "get", findClass("com.android.systemui.statusbar.phone.MiuiDripLeftStatusBarIconControllerImpl", lpparam.classLoader)); Object mDripIconManager = XposedHelpers.getObjectField(param.thisObject, "mDripLeftDarkIconManager"); ArrayList blockList = new ArrayList<>(); int mCurrentStatusBarType = (int) XposedHelpers.getAdditionalInstanceField(dripLeftController, "mCurrentStatusBarType"); if (mCurrentStatusBarType != 1) { blockList.addAll(dripLeftIcons); } XposedHelpers.callMethod(mDripIconManager, "setBlockList", blockList); XposedHelpers.callMethod(dripLeftController, "refreshIconGroup", mDripIconManager); } }); findAndHookMethod("com.android.systemui.statusbar.phone.MiuiPhoneStatusBarView", "setStatusBarType", int.class, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { int mCurrentStatusBarType = XposedHelpers.getIntField(param.thisObject, "mCurrentStatusBarType"); Object dripLeftController = XposedHelpers.callStaticMethod(findClass("com.android.systemui.Dependency", lpparam.classLoader), "get", findClass("com.android.systemui.statusbar.phone.MiuiDripLeftStatusBarIconControllerImpl", lpparam.classLoader)); XposedHelpers.setAdditionalInstanceField(dripLeftController, "mCurrentStatusBarType", mCurrentStatusBarType); } }); } if (isMoveLeft || isNetworkSpeedAtRightEnable) { hookAllMethods("com.android.systemui.statusbar.phone.MiuiPhoneStatusBarView", "updateCutoutLocation", new MethodHook() { @Override protected void after(MethodHookParam param) { int mCurrentStatusBarType = (int) XposedHelpers.getObjectField(param.thisObject, "mCurrentStatusBarType"); if (mCurrentStatusBarType == 1) { if (isNetworkSpeedAtRightEnable) { Object mDripNetworkSpeedView = XposedHelpers.getObjectField(param.thisObject, "mDripNetworkSpeedView"); XposedHelpers.callMethod(mDripNetworkSpeedView, "setBlocked", true); } } else { boolean dualRows = false; if (isMoveLeft && !dualRows) { View mDripStatusBarLeftStatusIconArea = (View) XposedHelpers.getObjectField(param.thisObject, "mDripStatusBarLeftStatusIconArea"); mDripStatusBarLeftStatusIconArea.setVisibility(View.VISIBLE); } } } }); } if (isNetworkSpeedAtRightEnable) { hookAllMethods("com.android.systemui.statusbar.policy.NetworkSpeedController", "setDripNetworkSpeedView", new MethodHook() { @Override protected void before(MethodHookParam param) { param.args[0] = null; } }); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/StatusBarSimIcon.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object StatusBarSimIcon : BaseHook() { override fun init() { loadClass("com.android.systemui.statusbar.phone.StatusBarSignalPolicy").methodFinder().first { name == "hasCorrectSubs" && parameterTypes[0] == MutableList::class.java }.createHook { before { val list = it.args[0] as MutableList<*> /* val size = list.size*/ if (mPrefsMap.getStringAsInt("system_ui_status_bar_icon_mobile_network_signal_card_2", 0) == 2) { list.removeAt(1) } if (mPrefsMap.getStringAsInt("system_ui_status_bar_icon_mobile_network_signal_card_1", 0) == 2) { list.removeAt(0) } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/all/WifiNetworkIndicator.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.all import android.view.View import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XposedHelpers object WifiNetworkIndicator : BaseHook() { var mVisibility = 0 private var mStatusBarWifiView: Class<*>? = null override fun init() { mStatusBarWifiView = findClassIfExists("com.android.systemui.statusbar.StatusBarWifiView") val mWifiNetworkIndicator = mPrefsMap.getStringAsInt("system_ui_status_bar_icon_wifi_network_indicator", 0) when (mWifiNetworkIndicator) { 1 -> mVisibility = View.VISIBLE 2 -> mVisibility = View.INVISIBLE } val hideWifiActivity: MethodHook = object : MethodHook() { override fun after(param: MethodHookParam) { val mWifiActivityView = XposedHelpers.getObjectField(param.thisObject, "mWifiActivityView") XposedHelpers.callMethod(mWifiActivityView, "setVisibility", mVisibility) } } hookAllMethods(mStatusBarWifiView, "applyWifiState", hideWifiActivity) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/icon/t/UseNewHD.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.icon.t import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object UseNewHD : BaseHook() { // 仅供 Android 13 设备使用,部分未进版机型依旧不可用 override fun init() { runCatching { loadClass("com.android.systemui.statusbar.policy.HDController").methodFinder().first { name == "isVisible" }.createHook { returnConstant(true) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/layout/StatusBarLayout.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.layout import android.annotation.SuppressLint import android.app.KeyguardManager import android.content.Context import android.content.res.Configuration import android.content.res.Resources import android.view.Gravity import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView import androidx.constraintlayout.widget.ConstraintLayout import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.api.dp2px import com.sevtinge.cemiuiler.utils.getObjectFieldAs import com.sevtinge.cemiuiler.utils.isStatic object StatusBarLayout : BaseHook() { private val getMode = mPrefsMap.getStringAsInt("system_ui_statusbar_layout_mode", 0) private val isCompatibilityMode = mPrefsMap.getBoolean("system_ui_statusbar_layout_compatibility_mode") private var statusBarLeft = 0 private var statusBarTop = 0 private var statusBarRight = 0 private var statusBarBottom = 0 @SuppressLint("DiscouragedApi") override fun init() { val collapsedStatusBarFragmentClass = loadClass("com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment") val phoneStatusBarView = loadClass("com.android.systemui.statusbar.phone.PhoneStatusBarView") var mLeftLayout: LinearLayout? = null var mRightLayout: LinearLayout? = null var mCenterLayout: LinearLayout? var statusBar: ViewGroup? = null // 判断屏幕状态更新布局 mode: 1正常布局 2居中布局 fun updateLayout(context: Context, mode: Int) { when (mode) { 1 -> { val mConfiguration: Configuration = context.resources.configuration if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { // 横屏 statusBar?.setPadding( statusBarLeft, statusBarTop, statusBarRight, statusBarBottom ) } } 2 -> { val mConfiguration: Configuration = context.resources.configuration if (mConfiguration.orientation == Configuration.ORIENTATION_PORTRAIT) { // 横屏 mLeftLayout?.setPadding(statusBarLeft, 0, 0, 0) mRightLayout?.setPadding(0, 0, statusBarRight, 0) statusBar?.setPadding(0, statusBarTop, 0, statusBarBottom) } else { // 竖屏 mLeftLayout?.setPadding(0, 0, 0, 0) mRightLayout?.setPadding(0, 0, 0, 0) } } } } // 判断是否开启挖孔兼容模式 if (isCompatibilityMode) { loadClass("com.android.systemui.ScreenDecorations").methodFinder().first { name == "boundsFromDirection" && parameterCount == 3 && isStatic }.createHook { before { it.args[1] = 0 } } } // 修改对应布局 when (getMode) { // 默认 0 -> { collapsedStatusBarFragmentClass.methodFinder() .filterByName("onViewCreated") .filterByParamCount(2) .first().createHook { after { param -> val miuiPhoneStatusBarView = param.thisObject.getObjectFieldAs("mStatusBar") val context: Context = miuiPhoneStatusBarView.context val res: Resources = miuiPhoneStatusBarView.resources val statusBarId: Int = res.getIdentifier("status_bar", "id", "com.android.systemui") statusBar = miuiPhoneStatusBarView.findViewById(statusBarId) if (statusBar == null) return@after statusBarLeft = statusBar!!.paddingLeft statusBarTop = statusBar!!.paddingTop statusBarRight = statusBar!!.paddingRight statusBarBottom = statusBar!!.paddingBottom if (isCompatibilityMode) { /*val customLeftMargin = mPrefsMap.getStringAsInt("status_bar_left_margin", 0) if (customLeftMargin != 0) { statusBarLeft = customLeftMargin } val customRightMargin = mPrefsMap.getStringAsInt("status_bar_right_margin", 0) if (customRightMargin != 0) { statusBarRight = customRightMargin }*/ updateLayout(context, 1) } } } // 兼容模式 phoneStatusBarView.methodFinder() .filterByName("updateLayoutForCutout") .first().createHook { after { if (isCompatibilityMode) { val context = (it.thisObject as ViewGroup).context updateLayout(context, 1) } } } } // 时钟居中 1 -> { collapsedStatusBarFragmentClass.methodFinder() .filterByName("onViewCreated") .filterByParamCount(2) .first().createHook { after { param -> val miuiPhoneStatusBarView = param.thisObject.getObjectFieldAs("mStatusBar") val context: Context = miuiPhoneStatusBarView.context val res: Resources = miuiPhoneStatusBarView.resources val statusBarId: Int = res.getIdentifier("status_bar", "id", "com.android.systemui") val statusBarContentsId: Int = res.getIdentifier( "status_bar_contents", "id", "com.android.systemui" ) val systemIconAreaId: Int = res.getIdentifier("system_icon_area", "id", "com.android.systemui") val clockId: Int = res.getIdentifier("clock", "id", "com.android.systemui") val phoneStatusBarLeftContainerId: Int = res.getIdentifier( "phone_status_bar_left_container", "id", "com.android.systemui" ) val notificationIconAreaInnerId: Int = res.getIdentifier( "notification_icon_area_inner", "id", "com.android.systemui" ) statusBar = miuiPhoneStatusBarView.findViewById(statusBarId) val statusBarContents: ViewGroup = miuiPhoneStatusBarView.findViewById(statusBarContentsId) if (statusBar == null) return@after val clock: TextView = miuiPhoneStatusBarView.findViewById(clockId) val phoneStatusBarLeftContainer: ViewGroup = miuiPhoneStatusBarView.findViewById( phoneStatusBarLeftContainerId ) val notificationIconAreaInner: ViewGroup = miuiPhoneStatusBarView.findViewById( notificationIconAreaInnerId ) val systemIconArea: ViewGroup = miuiPhoneStatusBarView.findViewById(systemIconAreaId) (clock.parent as ViewGroup).removeView(clock) (phoneStatusBarLeftContainer.parent as ViewGroup).removeView( phoneStatusBarLeftContainer ) (notificationIconAreaInner.parent as ViewGroup).removeView( notificationIconAreaInner ) (systemIconArea.parent as ViewGroup).removeView(systemIconArea) val mConstraintLayout = ConstraintLayout(context).also { it.layoutParams = ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT ) } mConstraintLayout.addView(notificationIconAreaInner) val fullscreenNotificationIconAreaLp = LinearLayout.LayoutParams( ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT ) notificationIconAreaInner.layoutParams = fullscreenNotificationIconAreaLp // 增加一个左对齐布局 mLeftLayout = LinearLayout(context) val leftLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams( 0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f ) mLeftLayout!!.layoutParams = leftLp mLeftLayout!!.gravity = Gravity.START or Gravity.CENTER_VERTICAL // 增加一个居中布局 mCenterLayout = LinearLayout(context) val centerLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT ) mCenterLayout!!.layoutParams = centerLp mCenterLayout!!.gravity = Gravity.CENTER or Gravity.CENTER_VERTICAL mRightLayout = LinearLayout(context) val rightLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams( 0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f ) mRightLayout!!.layoutParams = rightLp mRightLayout!!.gravity = Gravity.END or Gravity.CENTER_VERTICAL mLeftLayout!!.addView(phoneStatusBarLeftContainer) mLeftLayout!!.addView(mConstraintLayout) mCenterLayout!!.addView(clock) mRightLayout!!.addView(systemIconArea) statusBarContents.addView(mLeftLayout, 0) statusBarContents.addView(mCenterLayout) statusBarContents.addView(mRightLayout) statusBarLeft = statusBar!!.paddingLeft statusBarTop = statusBar!!.paddingTop statusBarRight = statusBar!!.paddingRight statusBarBottom = statusBar!!.paddingBottom if (isCompatibilityMode) { /* val customLeftMargin = mPrefsMap.getStringAsInt("status_bar_left_margin", 0) if (customLeftMargin != 0) { statusBarLeft = customLeftMargin } val customRightMargin = mPrefsMap.getStringAsInt("status_bar_right_margin", 0) if (customRightMargin != 0) { statusBarRight = customRightMargin }*/ updateLayout(context, 2) } } } phoneStatusBarView.methodFinder() .filterByName("updateLayoutForCutout") .first().createHook { after { if (mPrefsMap.getBoolean("layout_compatibility_mode")) { val context = (it.thisObject as ViewGroup).context updateLayout(context, 2) } } } } // 时钟居右 2 -> { collapsedStatusBarFragmentClass.methodFinder() .filterByName("onViewCreated") .filterByParamCount(2) .first().createHook { after { param -> val miuiPhoneStatusBarView = param.thisObject.getObjectFieldAs("mStatusBar") val context: Context = miuiPhoneStatusBarView.context val res: Resources = miuiPhoneStatusBarView.resources // 组件ID val statusBarId: Int = res.getIdentifier("status_bar", "id", "com.android.systemui") val clockId: Int = res.getIdentifier("clock", "id", "com.android.systemui") val batteryId: Int = res.getIdentifier("battery", "id", "com.android.systemui") // 查找组件 statusBar = miuiPhoneStatusBarView.findViewById(statusBarId) if (statusBar == null) return@after val clock: TextView = miuiPhoneStatusBarView.findViewById(clockId) val battery: ViewGroup = miuiPhoneStatusBarView.findViewById(batteryId) // 新建布局 val rightLp = LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT ).also { it.marginStart = dp2px(context, 5f) } mRightLayout = LinearLayout(context).also { it.layoutParams = rightLp } // 添加布局与组件 battery.addView(mRightLayout) (clock.parent as ViewGroup).removeView(clock) mRightLayout!!.addView(clock) statusBarLeft = statusBar!!.paddingLeft statusBarTop = statusBar!!.paddingTop statusBarRight = statusBar!!.paddingRight statusBarBottom = statusBar!!.paddingBottom if (isCompatibilityMode) { /*val customLeftMargin = mPrefsMap.getStringAsInt("status_bar_left_margin", 0) if (customLeftMargin != 0) { statusBarLeft = customLeftMargin } val customRightMargin = mPrefsMap.getStringAsInt("status_bar_right_margin", 0) if (customRightMargin != 0) { statusBarRight = customRightMargin }*/ updateLayout(context, 1) } } } // 兼容模式 phoneStatusBarView.methodFinder() .filterByName("updateLayoutForCutout") .first().createHook { after { if (isCompatibilityMode) { val context = (it.thisObject as ViewGroup).context updateLayout(context, 1) } } } } // 时钟居中+图标居左 3 -> { collapsedStatusBarFragmentClass.methodFinder() .filterByName("onViewCreated") .filterByParamCount(2) .first().createHook { after { param -> val miuiPhoneStatusBarView = param.thisObject.getObjectFieldAs("mStatusBar") val context: Context = miuiPhoneStatusBarView.context val res: Resources = miuiPhoneStatusBarView.resources val statusBarId: Int = res.getIdentifier("status_bar", "id", "com.android.systemui") val statusBarContentsId: Int = res.getIdentifier( "status_bar_contents", "id", "com.android.systemui" ) val systemIconAreaId: Int = res.getIdentifier("system_icon_area", "id", "com.android.systemui") val clockId: Int = res.getIdentifier("clock", "id", "com.android.systemui") val phoneStatusBarLeftContainerId: Int = res.getIdentifier( "phone_status_bar_left_container", "id", "com.android.systemui" ) val fullscreenNotificationIconAreaId: Int = res.getIdentifier( "fullscreen_notification_icon_area", "id", "com.android.systemui" ) val statusIconsId: Int = res.getIdentifier( "statusIcons", "id", "com.android.systemui" ) val systemIconsId: Int = res.getIdentifier( "system_icons", "id", "com.android.systemui" ) val batteryId: Int = res.getIdentifier( "battery", "id", "com.android.systemui" ) statusBar = miuiPhoneStatusBarView.findViewById(statusBarId) val statusBarContents: ViewGroup = miuiPhoneStatusBarView.findViewById(statusBarContentsId) if (statusBar == null) return@after val clock: TextView = miuiPhoneStatusBarView.findViewById(clockId) val phoneStatusBarLeftContainer: ViewGroup = miuiPhoneStatusBarView.findViewById( phoneStatusBarLeftContainerId ) val fullscreenNotificationIconArea: ViewGroup = miuiPhoneStatusBarView.findViewById( fullscreenNotificationIconAreaId ) val systemIconArea: ViewGroup = miuiPhoneStatusBarView.findViewById(systemIconAreaId) val statusIcons: ViewGroup = miuiPhoneStatusBarView.findViewById(statusIconsId) val systemIcons: ViewGroup = miuiPhoneStatusBarView.findViewById(systemIconsId) val battery: ViewGroup = miuiPhoneStatusBarView.findViewById(batteryId) (clock.parent as ViewGroup).removeView(clock) (phoneStatusBarLeftContainer.parent as ViewGroup).removeView( phoneStatusBarLeftContainer ) (systemIconArea.parent as ViewGroup).removeView(systemIconArea) (statusIcons.parent as ViewGroup).removeView(statusIcons) (systemIcons.parent as ViewGroup).removeView(systemIcons) (battery.parent as ViewGroup).removeView(battery) (fullscreenNotificationIconArea.parent as ViewGroup).removeView( fullscreenNotificationIconArea ) val mConstraintLayout = ConstraintLayout(context).also { it.layoutParams = ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.MATCH_PARENT, ConstraintLayout.LayoutParams.MATCH_PARENT ) } mConstraintLayout.addView(fullscreenNotificationIconArea) mConstraintLayout.addView(battery) battery.layoutParams = ConstraintLayout.LayoutParams( ConstraintLayout.LayoutParams.WRAP_CONTENT, ConstraintLayout.LayoutParams.MATCH_PARENT ).also { it.endToEnd = 0 } fullscreenNotificationIconArea.layoutParams = ConstraintLayout.LayoutParams( 0, ConstraintLayout.LayoutParams.MATCH_PARENT ).also { it.startToEnd = batteryId it.endToEnd = 0 } fullscreenNotificationIconArea.layoutDirection = View.LAYOUT_DIRECTION_RTL // 增加一个左对齐布局 mLeftLayout = LinearLayout(context) val leftLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams( 0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f ) mLeftLayout!!.layoutParams = leftLp mLeftLayout!!.gravity = Gravity.START or Gravity.CENTER_VERTICAL // 增加一个居中布局 mCenterLayout = LinearLayout(context) val centerLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT ) mCenterLayout!!.layoutParams = centerLp mCenterLayout!!.gravity = Gravity.CENTER or Gravity.CENTER_VERTICAL // 增加一个右布局 mRightLayout = LinearLayout(context) val rightLp: LinearLayout.LayoutParams = LinearLayout.LayoutParams( 0, LinearLayout.LayoutParams.MATCH_PARENT, 1.0f ) mRightLayout!!.layoutParams = rightLp mRightLayout!!.gravity = Gravity.END or Gravity.CENTER_VERTICAL mLeftLayout!!.addView(phoneStatusBarLeftContainer) mLeftLayout!!.addView(statusIcons) statusIcons.layoutDirection = View.LAYOUT_DIRECTION_RTL mCenterLayout!!.addView(clock) mRightLayout!!.addView(mConstraintLayout) fullscreenNotificationIconArea.layoutDirection = View.LAYOUT_DIRECTION_RTL statusBarContents.addView(mLeftLayout, 0) statusBarContents.addView(mCenterLayout) statusBarContents.addView(mRightLayout) statusBarLeft = statusBar!!.paddingLeft statusBarTop = statusBar!!.paddingTop statusBarRight = statusBar!!.paddingRight statusBarBottom = statusBar!!.paddingBottom if (isCompatibilityMode) { /*val customLeftMargin = mPrefsMap.getStringAsInt("status_bar_left_margin", 0) if (customLeftMargin != 0) { statusBarLeft = customLeftMargin } val customRightMargin = mPrefsMap.getStringAsInt("status_bar_right_margin", 0) if (customRightMargin != 0) { statusBarRight = customRightMargin }*/ updateLayout(context, 2) } } } // 兼容模式 phoneStatusBarView.methodFinder() .filterByName("updateLayoutForCutout") .first().createHook { after { if (isCompatibilityMode) { val context = (it.thisObject as ViewGroup).context updateLayout(context, 2) } } } // 解决重叠 loadClass("com.android.systemui.statusbar.phone.MiuiCollapsedStatusBarFragment").methodFinder() .filterByName("showClock") .filterByParamTypes(Boolean::class.java) .first().createHook { after { val miuiPhoneStatusBarView = it.thisObject.getObjectFieldAs("mStatusBar") val res = miuiPhoneStatusBarView.resources val statusBarId = res.getIdentifier("status_bar", "id", "com.android.systemui") val statusBar1 = miuiPhoneStatusBarView.findViewById(statusBarId) // 非锁屏下整个状态栏布局 val keyguardMgr = statusBar1.context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager if (keyguardMgr.isKeyguardLocked) { statusBar1!!.visibility = View.GONE } else { statusBar1!!.visibility = View.VISIBLE } } } // 修改图标的顺序 /*findConstructor("com.android.systemui.statusbar.phone.StatusBarIconList") { parameterCount == 1 }.hookBefore { }*/ } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/model/MobileTypeSingleHook.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.model import android.annotation.SuppressLint import android.content.Context import android.graphics.Typeface import android.util.TypedValue import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import com.sevtinge.cemiuiler.utils.setObjectField import de.robv.android.xposed.XposedHelpers object MobileTypeSingleHook : BaseHook() { // 初始化开关 private val getLocation by lazy { // 显示在信号左侧 mPrefsMap.getBoolean("system_ui_statusbar_mobile_type_left") } private val isOnlyShowNetwork by lazy { // 仅显示上网卡 mPrefsMap.getBoolean("system_ui_statusbar_mobile_type_only_show_network") } private val bold by lazy { // 加粗 mPrefsMap.getBoolean("system_ui_statusbar_mobile_type_bold") } private val fontSize by lazy { // 字体大小 mPrefsMap.getInt("system_ui_statusbar_mobile_type_font_size", 27) } private val leftMargin by lazy { // 左侧间距 mPrefsMap.getInt("system_ui_statusbar_mobile_type_left_margin", 7) } private val rightMargin by lazy { // 右侧间距 mPrefsMap.getInt("system_ui_statusbar_mobile_type_right_margin", 0) } private val verticalOffset by lazy { // 上下偏移量 mPrefsMap.getInt("system_ui_statusbar_mobile_type_vertical_offset", 8) } @SuppressLint("DiscouragedApi") override fun init() { val statusBarMobileClass by lazy { loadClass("com.android.systemui.statusbar.StatusBarMobileView") } // 兼容图标异常空位的问题,一些机器不需要这两个 hook val showSingleMobileType: MethodHook = object : MethodHook(PRIORITY_HIGHEST) { override fun before(param: MethodHookParam) { val mobileIconState = param.args[0] XposedHelpers.setObjectField(mobileIconState, "showMobileDataTypeSingle", true) XposedHelpers.setObjectField(mobileIconState, "fiveGDrawableId", 0) } } hookAllMethods("com.android.systemui.statusbar.StatusBarMobileView", "applyMobileState", showSingleMobileType) val afterUpdate: MethodHook = object : MethodHook() { override fun after(param: MethodHookParam) { val mMobileLeftContainer = XposedHelpers.getObjectField(param.thisObject, "mMobileLeftContainer") XposedHelpers.callMethod(mMobileLeftContainer, "setVisibility", 8) } } hookAllMethods("com.android.systemui.statusbar.StatusBarMobileView", "applyMobileState", afterUpdate) // 使网络类型单独显示 statusBarMobileClass.methodFinder().first { name == "applyMobileState" }.createHook { before { val mobileIconState = it.args[0] mobileIconState.setObjectField("showMobileDataTypeSingle", true) } } try { statusBarMobileClass.methodFinder().first { name == "init" }.createHook { after { val mContext = XposedHelpers.getObjectField(it.thisObject, "mContext") as Context val res = mContext.resources val mobileLeftContainer = XposedHelpers.getObjectField(it.thisObject, "mMobileLeftContainer") as ViewGroup val mobileGroup = XposedHelpers.getObjectField(it.thisObject, "mMobileGroup") as LinearLayout val mobileTypeSingle = XposedHelpers.getObjectField(it.thisObject, "mMobileTypeSingle") as TextView /*val mobileIconState = it.args[0] val context: Context = statusBarMobileView.context val res: Resources = context.resources*/ // 获取组件 /*val mobileContainerLeftId: Int = res.getIdentifier("mobile_container_left", "id", "com.android.systemui") val mobileContainerLeft = statusBarMobileView.findViewById(mobileContainerLeftId) val statusBarMobileView = it.thisObject as ViewGroup val mobileGroupId: Int = res.getIdentifier("mobile_group", "id", "com.android.systemui") val mobileGroup = statusBarMobileView.findViewById(mobileGroupId) val mobileTypeSingleId: Int = res.getIdentifier("mobile_type_single", "id", "com.android.systemui") val mobileTypeSingle = statusBarMobileView.findViewById(mobileTypeSingleId)*/ // 移动网络类型图标显示位置 if (!getLocation) { mobileGroup.removeView(mobileTypeSingle) mobileGroup.addView(mobileTypeSingle) mobileGroup.removeView(mobileLeftContainer) mobileGroup.addView(mobileLeftContainer) } // 自定义样式 if (fontSize != 27) { mobileTypeSingle.textSize = fontSize * 0.5f } if (bold) { mobileTypeSingle.typeface = Typeface.DEFAULT_BOLD } val marginLeft = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, leftMargin * 0.5f, res.displayMetrics ).toInt() val marginRight = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, rightMargin * 0.5f, res.displayMetrics ).toInt() var topMargin = 0 if (verticalOffset != 8) { val marginTop = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, (verticalOffset - 8) * 0.5f, res.displayMetrics ) topMargin = marginTop.toInt() } mobileTypeSingle.setPaddingRelative(marginLeft, topMargin, marginRight, 0) // it.thisObject.callMethod("updateState", mobileIconState) } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } // 显示非上网卡的大图标 /*if (!isOnlyShowNetwork) { statusBarMobileClass.methodFinder().first { name == "updateState" }.createHook { after { val mobileIconState = it.args[0] val statusBarMobileView = it.thisObject as ViewGroup val context: Context = statusBarMobileView.context val res: Resources = context.resources val mobileTypeSingleId: Int = res.getIdentifier("mobile_type_single", "id", "com.android.systemui") val mobileTypeSingle = statusBarMobileView.findViewById(mobileTypeSingleId) if (!mobileIconState.getObjectFieldAs("dataConnected") && !mobileIconState.getObjectFieldAs("wifiAvailable")) { mobileTypeSingle.visibility = View.VISIBLE } } } }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/model/MobileTypeTextCustom.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.model import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook object MobileTypeTextCustom : BaseHook() { override fun init() { loadClass("com.android.systemui.statusbar.connectivity.MobileSignalController").methodFinder().first { name == "getMobileTypeName" && parameterTypes[0] == Int::class.java }.createHook { after { it.result = mPrefsMap.getString("system_ui_status_bar_mobile_type_custom", "ERR") } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/network/NetworkSpeed.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network import android.content.Context import android.net.ConnectivityManager import android.net.NetworkCapabilities import android.net.TrafficStats import android.util.Pair import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.R import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers import com.sevtinge.cemiuiler.utils.devicesdk.getAndroidVersion import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XposedHelpers import java.net.NetworkInterface import kotlin.math.pow import kotlin.math.roundToLong object NetworkSpeed : BaseHook() { private var measureTime: Long = 0 private var newTxBytesFixed: Long = 0 private var newRxBytesFixed: Long = 0 private var txBytesTotal: Long = 0 private var rxBytesTotal: Long = 0 private var txSpeed: Long = 0 private var rxSpeed: Long = 0 private var txArrow = "" private var rxArrow = "" // 隐藏慢速 private val hideLow by lazy { mPrefsMap.getBoolean("system_ui_statusbar_network_speed_hide") } // 网速均低于设定值隐藏 private val allHideLow by lazy { mPrefsMap.getBoolean("system_ui_statusbar_network_speed_hide_all") } // 慢速水平 private val lowLevel by lazy { mPrefsMap.getInt("system_ui_statusbar_network_speed_hide_slow", 1) * 1024 } // 值和单位双排显示 private val fakeDualRow by lazy { mPrefsMap.getBoolean("system_ui_statusbar_network_speed_fakedualrow") } // 上下行网速双排显示 private val doubleUpDown by lazy { mPrefsMap.getBoolean("system_ui_statusbar_network_speed_show_up_down") } // 交换图标与网速位置 private val swapPlaces by lazy { mPrefsMap.getBoolean("system_ui_statusbar_network_speed_swap_places") } // 网速图标 private val icons by lazy { mPrefsMap.getString("system_ui_statusbar_network_speed_icon", "2").toInt() } private fun getTrafficBytes(): Pair { var tx = -1L var rx = -1L try { val list = NetworkInterface.getNetworkInterfaces() while (list.hasMoreElements()) { val iFace = list.nextElement() if (iFace.isUp && !iFace.isVirtual && !iFace.isLoopback && !iFace.isPointToPoint && "" != iFace.name) { tx += XposedHelpers.callStaticMethod(TrafficStats::class.java, "getTxBytes", iFace.name) as Long rx += XposedHelpers.callStaticMethod(TrafficStats::class.java, "getRxBytes", iFace.name) as Long } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) tx = TrafficStats.getTotalTxBytes() rx = TrafficStats.getTotalRxBytes() } return Pair(tx, rx) } // 网速计算与隐藏相关 private fun humanReadableByteCount(ctx: Context, bytes: Long): String { return try { val modRes = Helpers.getModuleRes(ctx) val hideSecUnit = mPrefsMap.getBoolean("system_ui_statusbar_network_speed_sec_unit") var unitSuffix = modRes.getString(R.string.system_ui_statusbar_network_speed_Bs) if (hideSecUnit) unitSuffix = "" var f = bytes / 1024.0f var expIndex = 0 if (f > 999.0f) { expIndex = 1 f /= 1024.0f } val pre = modRes.getString(R.string.system_ui_statusbar_network_speed_speedunits)[expIndex] if (mPrefsMap.getBoolean("system_ui_statusbar_network_speed_fakedualrow")) { (if (f < 100.0f) String.format("%.1f", f) else String.format("%.0f", f)) + "\n" + String.format("%s$unitSuffix", pre) } else { (if (f < 100.0f) String.format("%.1f", f) else String.format("%.0f", f)) + String.format("%s$unitSuffix", pre) } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) "" } } override fun init() { // 双排网速相关 val networkClass = when { getAndroidVersion() == 30 -> "com.android.systemui.statusbar.NetworkSpeedController" else -> "com.android.systemui.statusbar.policy.NetworkSpeedController" } val nscCls by lazy { findClassIfExists(networkClass, lpparam.classLoader) } if (nscCls == null) { XposedLogUtils.logE(TAG, "DetailedNetSpeedHook: No NetworkSpeed view or controller") } else { nscCls.methodFinder().first { name == "getTotalByte" }.createHook { after { val bytes = getTrafficBytes() txBytesTotal = bytes.first rxBytesTotal = bytes.second measureTime = System.nanoTime() } } nscCls.methodFinder().first { name == "updateNetworkSpeed" }.createHook { before { var isConnected = false val mContext = XposedHelpers.getObjectField(it.thisObject, "mContext") as Context val mConnectivityManager = mContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val nw = mConnectivityManager.activeNetwork if (nw != null) { val capabilities = mConnectivityManager.getNetworkCapabilities(nw) if (capabilities != null && (!(! capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && !capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))) ) { isConnected = true } } if (isConnected) { val nanoTime = System.nanoTime() var newTime = nanoTime - measureTime measureTime = nanoTime if (newTime == 0L) newTime = (4 * 10.0.pow(9.0)).roundToLong() val bytes = getTrafficBytes() val newTxBytes = bytes.first val newRxBytes = bytes.second newTxBytesFixed = newTxBytes - txBytesTotal newRxBytesFixed = newRxBytes - rxBytesTotal if (newTxBytesFixed < 0 || txBytesTotal == 0L) newTxBytesFixed = 0 if (newRxBytesFixed < 0 || rxBytesTotal == 0L) newRxBytesFixed = 0 txSpeed = (newTxBytesFixed / (newTime / 10.0.pow(9.0))).roundToLong() rxSpeed = (newRxBytesFixed / (newTime / 10.0.pow(9.0))).roundToLong() txBytesTotal = newTxBytes rxBytesTotal = newRxBytes } else { txSpeed = 0 rxSpeed = 0 } } } try { nscCls.methodFinder().filterByName("formatSpeed").filterByParamCount(2).first() } catch (t: Throwable) { nscCls.methodFinder().filterByName("updateText").filterByParamCount(1).first() }.createHook { before { when (icons) { 2 -> { txArrow = if (txSpeed < lowLevel) "△" else "▲" rxArrow = if (rxSpeed < lowLevel) "▽" else "▼" } 3 -> { txArrow = if (txSpeed < lowLevel) " ▵" else " ▴" rxArrow = if (rxSpeed < lowLevel) " ▿" else " ▾" } 4 -> { txArrow = if (txSpeed < lowLevel) " ☖" else " ☗" rxArrow = if (rxSpeed < lowLevel) " ⛉" else " ⛊" } 5 -> { txArrow = if (txSpeed < lowLevel) "↑" else "↑" rxArrow = if (rxSpeed < lowLevel) "↓" else "↓" } 6 -> { txArrow = if (txSpeed < lowLevel) "⇧" else "⇧" rxArrow = if (rxSpeed < lowLevel) "⇩" else "⇩" } } // 计算上行网速 val tx = if (hideLow && !allHideLow && txSpeed < lowLevel) "" else { if (swapPlaces) "$txArrow${humanReadableByteCount(it.args[0] as Context, txSpeed)}" else "${humanReadableByteCount(it.args[0] as Context, txSpeed)}$txArrow" } // 计算下行网速 val rx = if (hideLow && !allHideLow && rxSpeed < lowLevel) "" else { if (swapPlaces) "$rxArrow${humanReadableByteCount(it.args[0] as Context, rxSpeed)}" else "${humanReadableByteCount(it.args[0] as Context, rxSpeed)}$rxArrow" } // 计算总网速 val ax = humanReadableByteCount( it.args[0] as Context, newTxBytesFixed + newRxBytesFixed ) // 存储是否隐藏慢速的条件的结果 val isLowSpeed = hideLow && (txSpeed + rxSpeed) < lowLevel val isAllLowSpeed = hideLow && allHideLow && txSpeed < lowLevel && rxSpeed < lowLevel when { // 如果显示上下行网速并且不开值和单位双排显示,返回上下行网速的字符串 doubleUpDown && !fakeDualRow -> { if (isLowSpeed && !isAllLowSpeed) { it.result = "" } else if (isAllLowSpeed) { it.result = "" } else { it.result = "$tx\n$rx" } } // 如果开启值和单位双排显示,返回总网速的字符串 fakeDualRow -> { if (isLowSpeed) { it.result = "" } else { it.result = ax } } // 其他情况,对隐藏慢速判定,返回空字符串,其余不返回 else -> { if (isLowSpeed) { it.result = "" } } } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/network/NetworkSpeedSec.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook // 隐藏网速单位 object NetworkSpeedSec : BaseHook() { override fun init() { loadClass("com.android.systemui.statusbar.views.NetworkSpeedView").methodFinder().first { name == "setNetworkSpeed" && parameterCount == 1 }.createHook { before { if (it.args[0] != null) { val mText = (it.args[0] as String) .replace("/", "") .replace("s", "") .replace("\'", "") .replace("วิ", "") it.args[0] = mText } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/network/NetworkSpeedSpacing.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network import android.os.Build import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers object NetworkSpeedSpacing : BaseHook() { override fun init() { // 网速更新间隔 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android12+ 可用 Helpers.findAndHookMethod( "com.android.systemui.statusbar.policy.NetworkSpeedController", lpparam.classLoader, "postUpdateNetworkSpeedDelay", Long::class.javaPrimitiveType, object : MethodHook() { override fun before(param: MethodHookParam) { val originInterval = param.args[0] as Long if (originInterval == 4000L) { val newInterval = mPrefsMap.getInt("system_ui_statusbar_network_speed_update_spacing", 4) * 1000L param.args[0] = newInterval } } }) } if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) { // Android11 可用 Helpers.findAndHookMethod( "com.android.systemui.statusbar.NetworkSpeedController", lpparam.classLoader, "postUpdateNetworkSpeedDelay", Long::class.javaPrimitiveType, object : MethodHook() { override fun before(param: MethodHookParam) { val originInterval = param.args[0] as Long if (originInterval != 0L) { val intervalTime = mPrefsMap.getInt("system_ui_statusbar_network_speed_update_spacing", 4) * 1000L param.args[0] = intervalTime } } }) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/network/NetworkSpeedStyle.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network import android.graphics.Typeface import android.util.TypedValue import android.view.View import android.widget.TextView import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.devicesdk.isAndroidR import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XposedHelpers object NetworkSpeedStyle : BaseHook() { private val doubleLine by lazy { mPrefsMap.getBoolean("system_ui_statusbar_network_speed_detailed") && mPrefsMap.getBoolean("system_ui_statusbar_network_speed_show_up_down") } private val dualRow by lazy { mPrefsMap.getBoolean("system_ui_statusbar_network_speed_fakedualrow") } private val fontSize by lazy { mPrefsMap.getInt("system_ui_statusbar_network_speed_font_size", 13) } private val fontSizeEnable by lazy { mPrefsMap.getBoolean("system_ui_statusbar_network_speed_font_size_enable") } private val bold by lazy { mPrefsMap.getBoolean("system_ui_statusbar_network_speed_bold") } override fun init() { if (isAndroidR()) { // Android 11 or MIUI12.5 Need to hook Statusbar in Screen Lock interface, to set front size // Thanks for CustoMIUIzerMod loadClass("com.android.systemui.statusbar.phone.MiuiKeyguardStatusBarView").methodFinder().first { name == "onDensityOrFontScaleChanged" }.createHook { after { params -> val meter = XposedHelpers.getObjectField(params.thisObject, "mNetworkSpeedView") as TextView // 网速字体大小调整 if (fontSizeEnable) { try { if (doubleLine || dualRow) { meter.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSize * 0.5f) } else { meter.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSize.toFloat()) } } catch (e: Exception) { XposedLogUtils.logE(TAG, e) } } } } } hookAllConstructors("com.android.systemui.statusbar.views.NetworkSpeedView", object : MethodHook() { override fun after(param: MethodHookParam) { // 值和单位双排显示 + 上下行网速双排显示 val meter = param.thisObject as TextView if (dualRow) { mResHook.setObjectReplacement(lpparam.packageName, "string", "network_speed_suffix", "%1\$s\n%2\$s") } if (meter.tag == null || "slot_text_icon" != meter.tag) { // 网速字体大小调整 if (fontSizeEnable) { try { if (doubleLine || dualRow) { meter.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSize * 0.5f) } else { meter.setTextSize(TypedValue.COMPLEX_UNIT_DIP, fontSize.toFloat()) } } catch (e: Exception) { XposedLogUtils.logE(TAG, e) } } // 网速加粗 if (bold) { meter.typeface = Typeface.DEFAULT_BOLD } val res = meter.resources // 左侧间距 var leftMargin = mPrefsMap.getInt("system_ui_statusbar_network_speed_left_margin", 0) leftMargin = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, leftMargin * 0.5f, res.displayMetrics ).toInt() // 右侧间距 var rightMargin = mPrefsMap.getInt("system_ui_statusbar_network_speed_right_margin", 0) rightMargin = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, rightMargin * 0.5f, res.displayMetrics ).toInt() // 上下偏移量 var topMargin = 0 val verticalOffset = mPrefsMap.getInt("system_ui_statusbar_network_speed_vertical_offset", 8) if (verticalOffset != 8) { val marginTop = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, (verticalOffset - 8) * 0.5f, res.displayMetrics ) topMargin = marginTop.toInt() } meter.setPaddingRelative(leftMargin, topMargin, rightMargin, 0) // 水平对齐 when (mPrefsMap.getStringAsInt("system_ui_statusbar_network_speed_align", 1)) { 2 -> meter.textAlignment = View.TEXT_ALIGNMENT_TEXT_START 3 -> meter.textAlignment = View.TEXT_ALIGNMENT_CENTER 4 -> meter.textAlignment = View.TEXT_ALIGNMENT_TEXT_END } try { if (doubleLine || dualRow) { var spacing = 0.9f meter.isSingleLine = false meter.maxLines = 2 if (fontSize > 8.5f) { spacing = 0.9f } meter.setLineSpacing(0f, spacing) } } catch (e: Exception) { XposedLogUtils.logE(TAG, e) } } } } ) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/network/StatusBarNoNetSpeedSep.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network import android.view.View import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XposedHelpers object StatusBarNoNetSpeedSep : BaseHook() { override fun init() { loadClass("com.android.systemui.statusbar.views.NetworkSpeedSplitter", lpparam.classLoader).methodFinder() .first { name == "updateVisibility" }.createHook { before { XposedHelpers.setObjectField(it.thisObject, "mNetworkSpeedVisibility", View.GONE) } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/systemui/statusbar/network/s/NetworkSpeedWidth.kt ================================================ package com.sevtinge.cemiuiler.module.hook.systemui.statusbar.network.s import android.widget.TextView import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.Helpers import de.robv.android.xposed.XposedHelpers object NetworkSpeedWidth : BaseHook() { override fun init() { // 固定宽度以防相邻元素左右防抖 if (mPrefsMap.getInt("system_ui_statusbar_network_speed_fixedcontent_width", 10) > 10) { Helpers.hookAllMethods( "com.android.systemui.statusbar.views.NetworkSpeedView", lpparam.classLoader, "applyNetworkSpeedState", object : MethodHook() { override fun before(param: MethodHookParam) { val meter = param.thisObject as TextView if (meter.tag == null || "slot_text_icon" != meter.tag) { XposedHelpers.getAdditionalInstanceField(param.thisObject, "inited") } } } ) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/thememanager/DisableThemeAd.java ================================================ package com.sevtinge.cemiuiler.module.hook.thememanager; import com.sevtinge.cemiuiler.module.base.BaseHook; import miui.drm.DrmManager; public class DisableThemeAd extends BaseHook { Class mAdInfoCls; Class mAdInfoResponseCls; @Override public void init() { mAdInfoCls = findClassIfExists("com.android.thememanager.basemodule.ad.model.AdInfo"); mAdInfoResponseCls = findClassIfExists("com.android.thememanager.basemodule.ad.model.AdInfoResponse"); findAndHookMethod(mAdInfoResponseCls, "isAdValid", mAdInfoCls, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(false); } }); findAndHookMethod("com.android.thememanager.recommend.view.listview.viewholder.PureAdBannerViewHolder", "isAdValid", mAdInfoCls, new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(false); } }); } public void initZygote() { hookAllMethods(DrmManager.class, "isSupportAd", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.setResult(false); } }); hookAllMethods(DrmManager.class, "setSupportAd", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { param.args[1] = false; } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/thememanager/DisableThemeAdNew.kt ================================================ package com.sevtinge.cemiuiler.module.hook.thememanager import android.view.View import android.widget.FrameLayout import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.Log import com.github.kyuubiran.ezxhelper.finders.ConstructorFinder.`-Static`.constructorFinder import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import miui.drm.DrmManager class DisableThemeAdNew : BaseHook() { override fun init() { try { DrmManager::class.java.methodFinder().filterByName("isSupportAd").toList().createHooks { returnConstant(false) } } catch (t: Throwable) { Log.ex(t) } try { DrmManager::class.java.methodFinder().filterByName("setSupportAd").toList().createHooks { returnConstant(false) } } catch (t: Throwable) { Log.ex(t) } try { loadClass("com.android.thememanager.basemodule.ad.model.AdInfoResponse").methodFinder().filterByName("isAdValid").filterByParamCount(1).first() .createHook { returnConstant(false) } } catch (t: Throwable) { Log.ex(t) } removeAds(loadClass("com.android.thememanager.recommend.view.listview.viewholder.SelfFontItemAdViewHolder")) removeAds(loadClass("com.android.thememanager.recommend.view.listview.viewholder.SelfRingtoneItemAdViewHolder")) } private fun removeAds(clazz: Class<*>) { try { clazz.constructorFinder().filterByParamCount(2).first().createHook { after { if (it.args[0] != null) { val view = it.args[0] as View val params = FrameLayout.LayoutParams(0, 0) view.layoutParams = params view.visibility = View.GONE } } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/thememanager/EnableFoldTheme.java ================================================ package com.sevtinge.cemiuiler.module.hook.thememanager; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedHelpers; public class EnableFoldTheme extends BaseHook { @Override public void init() { findAndHookMethod("com.android.thememanager.ThemeApplication", "onCreate", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { XposedHelpers.setStaticObjectField(findClassIfExists("android.os.Build"), "DEVICE", "zizhan"); } }); findAndHookMethod("com.android.thememanager.basemodule.utils.r", "r", XC_MethodReplacement.returnConstant(true)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/thememanager/EnablePadTheme.java ================================================ package com.sevtinge.cemiuiler.module.hook.thememanager; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class EnablePadTheme extends BaseHook { @Override public void init() { /*findAndHookMethod("com.android.thememanager.basemodule.utils.r", "C", XC_MethodReplacement.returnConstant(true)); findAndHookMethod("com.android.thememanager.basemodule.utils.r", "D", XC_MethodReplacement.returnConstant(true));*/ findAndHookMethod("com.android.thememanager.ThemeApplication", "onCreate", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { XposedHelpers.setStaticBooleanField(findClassIfExists("miui.os.Build"), "IS_TABLET", true); } }); /*findAndHookMethod("com.android.thememanager.basemodule.utils.r", "r", XC_MethodReplacement.returnConstant(false)); findAndHookMethod("com.android.thememanager.basemodule.utils.r", "e", XC_MethodReplacement.returnConstant("dagu"));*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/thememanager/ThemeCrackNew.kt ================================================ package com.sevtinge.cemiuiler.module.hook.thememanager import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.Log import com.github.kyuubiran.ezxhelper.ObjectHelper.Companion.objectHelper import com.github.kyuubiran.ezxhelper.finders.FieldFinder.`-Static`.fieldFinder import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseXposedInit.mPrefsMap import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.closeDexKit import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.DexKit.initDexKit import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import com.sevtinge.cemiuiler.utils.setObjectField import de.robv.android.xposed.callbacks.XC_LoadPackage import miui.drm.DrmManager import java.io.File class ThemeCrackNew { val TAG = "ThemeCrackNew" fun init(lpparam: XC_LoadPackage.LoadPackageParam) { if (mPrefsMap.getBoolean("various_enable_super_function") && mPrefsMap.getBoolean("various_theme_crack")) return initDexKit(lpparam) try { loadClass("com.android.thememanager.detail.theme.model.OnlineResourceDetail").methodFinder().filterByName("toResource").toList().createHooks { after { it.thisObject.setObjectField("bought", true) } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } try { loadClass("com.android.thememanager.basemodule.views.DiscountPriceView").methodFinder().filterByParamCount(2) .filterByParamTypes(Int::class.java, Int::class.java).filterByReturnType(Void.TYPE).toList().createHooks { before { it.args[1] = 0 } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } try { loadClass("com.android.thememanager.recommend.view.listview.viewholder.LargeIconDetailRecommendViewHolder").methodFinder().filterByParamCount(1) .filterByParamTypes(Int::class.java).filterByReturnType(Void.TYPE).toList().createHooks { before { it.args[0] = 0 } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } try { loadClass("com.miui.maml.widget.edit.MamlutilKt").methodFinder().filterByName("themeManagerSupportPaidWidget").first().createHook { returnConstant(false) } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) } try { dexKitBridge.findMethod { matcher { addUsingStringsEquals("theme", "ThemeManagerTag", "/system", "check rights isLegal:") } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { after { it.result = DrmManager.DrmResult.DRM_SUCCESS } } dexKitBridge.findMethod { matcher { addUsingStringsEquals( "apply failed", "/data/system/theme/large_icons/", "default_large_icon_product_id", "largeicons", "relativePackageList is empty" ) } }.firstOrNull()?.getMethodInstance(lpparam.classLoader)?.createHook { before { val resource = it.thisObject.javaClass.fieldFinder().filterByType(loadClass("com.android.thememanager.basemodule.resource.model.Resource", lpparam.classLoader)).first() val productId = it.thisObject.objectHelper().getObjectOrNull(resource.name)!!.objectHelper().invokeMethodBestMatch("getProductId").toString() val strPath = "/storage/emulated/0/Android/data/com.android.thememanager/files/MIUI/theme/.data/rights/theme/${productId}-largeicons.mra" val file = File(strPath) val fileParent = file.parentFile!! if (!fileParent.exists()) fileParent.mkdirs() file.createNewFile() } } closeDexKit() } catch (t: Throwable) { Log.ex(t) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/thememanager/VersionCodeModify.java ================================================ package com.sevtinge.cemiuiler.module.hook.thememanager; import com.sevtinge.cemiuiler.module.base.BaseHook; public class VersionCodeModify extends BaseHook { Class mThemeApplication; @Override public void init() { mThemeApplication = findClassIfExists("com.android.thememanager.ThemeApplication"); findAndHookMethod(mThemeApplication, "onCreate", new MethodHook() { @Override protected void before(MethodHookParam param) { findAndHookMethod("android.os.SystemProperties", "get", String.class, String.class, new MethodHook() { @Override protected void before(MethodHookParam param) { if ("ro.miui.ui.version.code".equals(param.args[0])) { param.setResult("14"); } } }); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/tsmclient/AutoNfc.kt ================================================ package com.sevtinge.cemiuiler.module.hook.tsmclient import android.annotation.SuppressLint import android.content.Context import android.content.res.XModuleResources import android.nfc.NfcAdapter import android.widget.Toast import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.FieldFinder.`-Static`.fieldFinder import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.R import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.module.base.BaseXposedInit.mModulePath import com.sevtinge.cemiuiler.utils.callMethod import de.robv.android.xposed.callbacks.XC_InitPackageResources import kotlinx.coroutines.MainScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.lsposed.hiddenapibypass.HiddenApiBypass object AutoNfc : BaseHook() { @SuppressLint("SuspiciousIndentation") override fun init() { loadClass("com.miui.tsmclient.ui.quick.DoubleClickActivity").methodFinder().first { name == "onCreate" }.createHook { after { param -> if (!EzXHelper.isHostPackageNameInited) EzXHelper.initAppContext() NfcAdapter.getDefaultAdapter(EzXHelper.appContext).let { nfcAdapter -> if (nfcAdapter.isEnabled) return@after HiddenApiBypass.invoke(NfcAdapter::class.java, nfcAdapter, "enable") MainScope().launch { waitNFCEnable(EzXHelper.appContext, nfcAdapter) param.thisObject.javaClass.fieldFinder().filter { type == Boolean::class.java }.last().setBoolean(param.thisObject, false) val ctaHelperClazz = findClass("com.miui.tsmclient.entity.CTAHelper") param.thisObject.javaClass.fieldFinder().first { type == ctaHelperClazz }.get(param.thisObject)!!.callMethod("check") } } } } loadClass("com.miui.tsmclient.ui.quick.DoubleClickActivity").methodFinder().first { name == "onDestroy" }.createHook { before { NfcAdapter.getDefaultAdapter(EzXHelper.appContext).let { nfcAdapter -> HiddenApiBypass.invoke(NfcAdapter::class.java, nfcAdapter, "disable") } } } } fun initResource(resparam: XC_InitPackageResources.InitPackageResourcesParam) { val moduleRes = XModuleResources.createInstance(mModulePath, resparam.res) resparam.res.setReplacement( "com.miui.tsmclient", "string", "nfc_off_hint", moduleRes.fwd(R.string.tsmclient_nfc_turning_on) ) resparam.res.setReplacement( "com.miui.tsmclient", "string", "immediately_open", moduleRes.fwd(R.string.tsmclient_nfc_turn_on_manually) ) } private suspend fun waitNFCEnable(context: Context, nfcAdapter: NfcAdapter) { repeat(15) { if (!nfcAdapter.isEnabled) delay(300) else return@repeat if (it == 14) Toast.makeText(context, R.string.tsmclient_nfc_turn_on_failed, Toast.LENGTH_SHORT).show() } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/updater/DeviceModify.kt ================================================ package com.sevtinge.cemiuiler.module.hook.updater import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.hookBeforeMethod import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object DeviceModify : BaseHook() { private val deviceName: String = mPrefsMap.getString("updater_device", "") override fun init() { try { "android.os.SystemProperties".hookBeforeMethod( "get", String::class.java, String::class.java ) { if (it.args[0] == "ro.product.mod_device") it.result = deviceName } } catch (e: Throwable) { XposedLogUtils.logE(TAG, "[DeviceModify(Updater)]: android.os.SystemProperties hook failed", e) } try { "miuix.core.util.SystemProperties".hookBeforeMethod( "get", String::class.java, String::class.java ) { if (it.args[0] == "ro.product.mod_device") it.result = deviceName } } catch (e: Throwable) { XposedLogUtils.logE(TAG, "[DeviceModify(Updater)]: DeviceModify (Updater) miuix.core.util.SystemProperties hook failed", e) } dexKitBridge.findMethod { matcher { addUsingStringsEquals("android.os.SystemProperties", "get", "get e") } }.forEach { methodData -> methodData.getMethodInstance(lpparam.classLoader).hookBeforeMethod { if (it.args[0] == "ro.product.mod_device") it.result = deviceName } XposedLogUtils.logI("(Updater) dexkit method is $methodData") } /*try { val systemProperties = mUpdaterResultMethodsMap["SystemProperties"]!! assert(systemProperties.size == 1) val systemPropertiesDescriptor = systemProperties.first() val systemPropertiesMethod: Method = systemPropertiesDescriptor.getMethodInstance(lpparam.classLoader) systemPropertiesMethod.hookBeforeMethod { if (it.args[0] == "ro.product.mod_device") it.result = deviceName } XposedLogUtils.logI("(Updater) dexkit method is $systemPropertiesMethod") } catch (e: Throwable) { XposedBridge.log("[Cemiuiler][E][DeviceModify(Updater)]: DeviceModify (Updater) dexkit hook failed by $e") }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/updater/VabUpdate.kt ================================================ package com.sevtinge.cemiuiler.module.hook.updater import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook class VabUpdate : BaseHook() { override fun init() { loadClass("miui.util.FeatureParser").methodFinder().first { name == "hasFeature" && parameterCount == 2 }.createHook { before { if (it.args[0] == "support_ota_validate") { it.result = false } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/updater/VersionCodeModify.java ================================================ package com.sevtinge.cemiuiler.module.hook.updater; import android.os.Build; import android.text.TextUtils; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; public class VersionCodeModify extends BaseHook { Class mApplication; @Override public void init() { mApplication = findClassIfExists("com.android.updater.Application"); findAndHookMethod(mApplication, "onCreate", new MethodHook() { @Override protected void before(MethodHookParam param) { String mVersionCode = mPrefsMap.getString("various_updater_miui_version", "V14.0.22.11.26.DEV"); if (!TextUtils.isEmpty(mVersionCode)) { XposedHelpers.setStaticObjectField(Build.VERSION.class, "INCREMENTAL", mVersionCode); } } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/updater/VersionCodeNew.kt ================================================ package com.sevtinge.cemiuiler.module.hook.updater import android.os.Build import android.text.TextUtils import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import de.robv.android.xposed.XposedHelpers object VersionCodeNew : BaseHook() { private val mBigMethod by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("ro.miui.ui.version.name") } }.map { it.getMethodInstance(EzXHelper.classLoader) }.first() } private val mOSMethod by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("ro.mi.os.version.incremental", "version:") } }.map { it.getMethodInstance(EzXHelper.classLoader) }.first() } private val mOSCode by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("ro.mi.os.version.name", "OS") } }.map { it.getMethodInstance(EzXHelper.classLoader) }.first() } private val mOldVersionCode = mPrefsMap.getString("various_updater_big_version", "V816") private val mVersionCode = mPrefsMap.getString("various_updater_miui_version", "V14.0.22.11.26.DEV") override fun init() { // 原始修改版本名 val mApplication = findClassIfExists("com.android.updater.Application") findAndHookMethod(mApplication, "onCreate", object : MethodHook() { override fun before(param: MethodHookParam) { if (!TextUtils.isEmpty(mVersionCode)) { XposedHelpers.setStaticObjectField( Build.VERSION::class.java, "INCREMENTAL", "$mOldVersionCode.${mVersionCode.substringAfter(".")}" ) } } }) // 大版本名字修改 mBigMethod.createHook { before { if (!TextUtils.isEmpty(mOldVersionCode)) { it.result = mOldVersionCode } } } // OS 版本名修改 mOSMethod.createHook { before { if (!TextUtils.isEmpty(mVersionCode)) { it.result = mVersionCode } } } // OS 版本修改 mOSCode.createHook { before { if (!TextUtils.isEmpty(mVersionCode)) { it.result = "${mVersionCode.split(".")[0]}.${mVersionCode.split(".")[1]}.${mVersionCode.split(".")[2]}" } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/various/CollapseMiuiTitle.java ================================================ package com.sevtinge.cemiuiler.module.hook.various; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedHelpers; import miui.app.ActionBar; public class CollapseMiuiTitle extends BaseHook { @Override public void init() { Class abvCls = findClassIfExists("com.miui.internal.widget.AbsActionBarView"); int opt = mPrefsMap.getStringAsInt("various_collapse_miui_title", 0); if (abvCls != null) hookAllConstructors(abvCls, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { XposedHelpers.setIntField(param.thisObject, "mExpandState", ActionBar.STATE_EXPAND); XposedHelpers.setIntField(param.thisObject, "mInnerExpandState", ActionBar.STATE_COLLAPSE); if (opt == 2) XposedHelpers.setBooleanField(param.thisObject, "mResizable", false); } }); abvCls = findClassIfExists("miuix.appcompat.internal.app.widget.ActionBarView"); if (abvCls != null) hookAllConstructors(abvCls, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { try { setExpandState(param.thisObject, opt == 1 || opt == 3); setResizable(param.thisObject, opt == 3 || opt == 4); } catch (Throwable ignore) { } } }); } private void setExpandState(Object obj, boolean state) { if (state) { XposedHelpers.callMethod(obj, "setExpandState", ActionBar.STATE_COLLAPSE); } else { XposedHelpers.callMethod(obj, "setExpandState", ActionBar.STATE_EXPAND); } } private void setResizable(Object obj, boolean state) { if (state) { XposedHelpers.callMethod(obj, "setResizable", false); } else { XposedHelpers.callMethod(obj, "setResizable", true); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/various/DialogBlur.java ================================================ package com.sevtinge.cemiuiler.module.hook.various; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import de.robv.android.xposed.XposedHelpers; public class DialogBlur extends BaseHook { Class mDialogCls = findClassIfExists("miuix.appcompat.app.AlertController"); @Override public void init() { hookAllMethods(mDialogCls, "installContent", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { View mParentPanel = (View) XposedHelpers.getObjectField(param.thisObject, "mParentPanel"); if (mParentPanel != null) { /*new BlurUtils(mParentPanel);*/ new BlurUtils(mParentPanel, "default"); } } }); hookAllMethods(mDialogCls, "dismiss", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); View mParentPanel = (View) XposedHelpers.getObjectField(param.thisObject, "mParentPanel"); mParentPanel.setVisibility(View.INVISIBLE); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/various/DialogCustom.java ================================================ package com.sevtinge.cemiuiler.module.hook.various; import android.content.Context; import android.content.res.Configuration; import android.os.Build; import android.view.Gravity; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.FrameLayout; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import com.sevtinge.cemiuiler.utils.DisplayUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.Method; import java.util.LinkedList; import java.util.List; import de.robv.android.xposed.XposedHelpers; public class DialogCustom extends BaseHook { Context mContext; View mParentPanel = null; Class mAlertControllerCls; Class mDialogParentPanelCls; int mDialogGravity; int mDialogHorizontalMargin; int mDialogBottomMargin; @Override public void init() { if (lpparam.packageName.equals("com.miui.home")) { mAlertControllerCls = findClassIfExists("miui.home.lib.dialog.AlertController"); } else { mAlertControllerCls = findClassIfExists("miuix.appcompat.app.AlertController"); } mDialogParentPanelCls = findClassIfExists("miuix.internal.widget.DialogParentPanel"); List mAllMethodList = new LinkedList<>(); if (mPrefsMap.getBoolean("various_dialog_window_blur")) { hookAllConstructors(mAlertControllerCls, new MethodHook() { @Override protected void after(MethodHookParam param) { Window mWindow = (Window) XposedHelpers.getObjectField(param.thisObject, "mWindow"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { mWindow.getAttributes().setBlurBehindRadius(mPrefsMap.getInt("various_dialog_window_blur_radius", 60)); // android.R.styleable.Window_windowBlurBehindRadius } mWindow.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND); } }); } boolean oldMethodFound = false; if (mAlertControllerCls != null) { for (Method method : mAlertControllerCls.getDeclaredMethods()) { if ("setupDialogPanel".equals(method.getName())) { oldMethodFound = true; XposedLogUtils.logI(TAG, method.getName()); } mAllMethodList.add(method); } mDialogGravity = XposedInit.mPrefsMap.getStringAsInt("various_dialog_gravity", 0); mDialogHorizontalMargin = XposedInit.mPrefsMap.getInt("various_dialog_margin_horizontal", 0); mDialogBottomMargin = XposedInit.mPrefsMap.getInt("various_dialog_margin_bottom", 0); } if (oldMethodFound) { XposedLogUtils.logI(TAG, "oldMethod found."); findAndHookMethod(mAlertControllerCls, "setupDialogPanel", Configuration.class, new MethodHook() { @Override protected void after(MethodHookParam param) { mParentPanel = (View) XposedHelpers.getObjectField(param.thisObject, "mParentPanel"); mContext = mParentPanel.getContext(); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mParentPanel.getLayoutParams(); if (mDialogGravity != 0) { layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT; layoutParams.gravity = mDialogGravity == 1 ? Gravity.CENTER : Gravity.BOTTOM | Gravity.CENTER; layoutParams.setMarginStart(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.setMarginEnd(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.bottomMargin = mDialogGravity == 1 ? 0 : DisplayUtils.dip2px(mContext, mDialogBottomMargin); } mParentPanel.setLayoutParams(layoutParams); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { new BlurUtils(mParentPanel, "various_dialog_bg_blur"); } } }); } else { XposedLogUtils.logI(TAG, "oldMethod not found."); hookAllMethods(mAlertControllerCls, "updateDialogPanel", new MethodHook() { @Override protected void after(MethodHookParam param) { mParentPanel = (View) XposedHelpers.getObjectField(param.thisObject, "mParentPanel"); mContext = mParentPanel.getContext(); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mParentPanel.getLayoutParams(); if (mDialogGravity != 0) { layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT; layoutParams.gravity = mDialogGravity == 1 ? Gravity.CENTER : Gravity.BOTTOM | Gravity.CENTER; layoutParams.setMarginStart(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.setMarginEnd(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.bottomMargin = mDialogGravity == 1 ? 0 : DisplayUtils.dip2px(mContext, mDialogBottomMargin); } mParentPanel.setLayoutParams(layoutParams); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { new BlurUtils(mParentPanel, "various_dialog_bg_blur"); } } }); } try { hookAllMethods(mAlertControllerCls, "updateParentPanelMarginByWindowInsets", new MethodHook() { @Override protected void after(MethodHookParam param) { mParentPanel = (View) XposedHelpers.getObjectField(param.thisObject, "mParentPanel"); mContext = mParentPanel.getContext(); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mParentPanel.getLayoutParams(); if (mDialogGravity != 0) { layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT; layoutParams.gravity = mDialogGravity == 1 ? Gravity.CENTER : Gravity.BOTTOM | Gravity.CENTER; layoutParams.setMarginStart(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.setMarginEnd(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.bottomMargin = mDialogGravity == 1 ? 0 : DisplayUtils.dip2px(mContext, mDialogBottomMargin); } mParentPanel.setLayoutParams(layoutParams); } }); } catch (Exception e) { XposedLogUtils.logE(TAG, e); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/various/DialogGravity.java ================================================ package com.sevtinge.cemiuiler.module.hook.various; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogI; import android.content.Context; import android.content.res.Configuration; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import com.sevtinge.cemiuiler.utils.DisplayUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import de.robv.android.xposed.XposedHelpers; public class DialogGravity extends BaseHook { public static Context mContext; public static View mParentPanel = null; Class mDialogCls = XposedHelpers.findClassIfExists("miuix.appcompat.app.AlertController", lpparam.classLoader); Class mDialogParentPanelCls = XposedHelpers.findClassIfExists("miuix.internal.widget.DialogParentPanel", lpparam.classLoader); List methodList = new LinkedList<>(); @Override public void init() { if (mDialogCls != null) { boolean oldMethodFound = false; for (Method method : mDialogCls.getDeclaredMethods()) { if ("setupDialogPanel".equals(method.getName())) oldMethodFound = true; methodList.add(method); LogI(TAG, method.getName()); } int mDialogGravity = XposedInit.mPrefsMap.getStringAsInt("various_dialog_gravity", 0); int mDialogHorizontalMargin = XposedInit.mPrefsMap.getInt("various_dialog_horizontal_margin", 0); int mDialogBottomMargin = XposedInit.mPrefsMap.getInt("various_dialog_bottom_margin", 0); if (oldMethodFound) { findAndHookMethod(mDialogCls, "setupDialogPanel", Configuration.class, new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { mParentPanel = (View) XposedHelpers.getObjectField(param.thisObject, "mParentPanel"); mContext = mParentPanel.getContext(); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mParentPanel.getLayoutParams(); if (mDialogGravity != 0) { layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT; layoutParams.gravity = mDialogGravity == 1 ? Gravity.CENTER : Gravity.BOTTOM | Gravity.CENTER; layoutParams.setMarginStart(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.setMarginEnd(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.bottomMargin = mDialogGravity == 1 ? 0 : DisplayUtils.dip2px(mContext, mDialogBottomMargin); } mParentPanel.setLayoutParams(layoutParams); /*new BlurUtils(mParentPanel);*/ new BlurUtils(mParentPanel, "default"); } }); } for (Method method : methodList) { if (Arrays.equals(method.getParameterTypes(), new Class[]{Configuration.class}) && method.getReturnType() == Void.TYPE && method.getModifiers() == 2 && method.getParameterCount() == 1) { XposedLogUtils.logI(TAG, "2222" + method.getName()); XposedHelpers.findAndHookMethod(mDialogCls, method.getName(), new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { Field field = XposedHelpers.findFirstFieldByExactType(mDialogCls, mDialogParentPanelCls); mParentPanel = (View) field.get(param.thisObject); mContext = mParentPanel.getContext(); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mParentPanel.getLayoutParams(); if (mDialogGravity != 0) { layoutParams.width = FrameLayout.LayoutParams.MATCH_PARENT; layoutParams.gravity = mDialogGravity == 1 ? Gravity.CENTER : Gravity.BOTTOM | Gravity.CENTER; layoutParams.setMarginStart(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.setMarginEnd(mDialogHorizontalMargin == 0 ? 0 : DisplayUtils.dip2px(mContext, mDialogHorizontalMargin)); layoutParams.bottomMargin = mDialogGravity == 1 ? 0 : DisplayUtils.dip2px(mContext, mDialogBottomMargin); } mParentPanel.setLayoutParams(layoutParams); /*new BlurUtils(mParentPanel);*/ new BlurUtils(mParentPanel, "default"); } }); } } } hookAllMethods(mDialogCls, "dismiss", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); View mParentPanel = (View) XposedHelpers.getObjectField(param.thisObject, "mParentPanel"); mParentPanel.setVisibility(View.INVISIBLE); } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/various/MiuiAppNoOverScroll.java ================================================ package com.sevtinge.cemiuiler.module.hook.various; import android.view.View; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XposedHelpers; public class MiuiAppNoOverScroll extends BaseHook { @Override public void init() { Class mSpringBackCls = findClassIfExists("miuix.springback.view.SpringBackLayout"); Class mRemixRvCls = findClassIfExists("androidx.recyclerview.widget.RemixRecyclerView"); try { MethodHook hookParam = new MethodHook() { @Override protected void before(MethodHookParam param) { XposedHelpers.setBooleanField(param.thisObject, "mSpringBackEnable", false); param.args[0] = false; } }; if (mSpringBackCls != null) { hookAllConstructors(mSpringBackCls, new MethodHook() { @Override protected void after(MethodHookParam param) { XposedHelpers.setBooleanField(param.thisObject, "mSpringBackEnable", false); } }); findAndHookMethodSilently(mSpringBackCls, "setSpringBackEnable", boolean.class, hookParam); } if (mRemixRvCls != null) { hookAllConstructors(mRemixRvCls, new MethodHook() { @Override protected void after(MethodHookParam param) { ((View) param.thisObject).setOverScrollMode(View.OVER_SCROLL_NEVER); XposedHelpers.setBooleanField(param.thisObject, "mSpringBackEnable", false); } }); findAndHookMethodSilently(mRemixRvCls, "setSpringEnabled", boolean.class, hookParam); } } catch (Exception e) { XposedLogUtils.logE(TAG,"TAG" + lpparam.packageName, e); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/various/NoAccessDeviceLogsRequest.kt ================================================ package com.sevtinge.cemiuiler.module.hook.various import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedHelpers object NoAccessDeviceLogsRequest : BaseHook() { private lateinit var mActivityManagerInternal: Any private lateinit var mLogcatManagerService: Any override fun init() { val logAccessClient = loadClass( "com.android.server.logcat.LogcatManagerService\$LogAccessClient", lpparam.classLoader ) XposedHelpers.findAndHookMethod( "com.android.server.logcat.LogcatManagerService", lpparam.classLoader, "onStart", object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) { try { mLogcatManagerService = param.thisObject mActivityManagerInternal = XposedHelpers.getObjectField( mLogcatManagerService, "mActivityManagerInternal" ) } catch (t: Throwable) { XposedLogUtils.logE(TAG, "NoAccessDeviceLogsRequest -> onStart", t) } } } ) XposedHelpers.findAndHookMethod( "com.android.server.logcat.LogcatManagerService", lpparam.classLoader, "processNewLogAccessRequest", logAccessClient, object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) { try { val client = param.args[0] if (client == null || mActivityManagerInternal == null) return val uid = XposedHelpers.getIntField(client, "mUid") val packageName = XposedHelpers.getObjectField(client, "mPackageName") as String XposedHelpers.callMethod( mLogcatManagerService, "onAccessApprovedForClient", client ) // debug 用,取消禁用详细日志输出可进行调试 XposedLogUtils.logI("NoAccessDeviceLogsRequest bypass for package=$packageName uid=$uid") param.result = null } catch (t: Throwable) { // 输出异常日志 XposedLogUtils.logE("NoAccessDeviceLogsRequest -> processNewLogAccessRequest", t) } } }) // 米客原来的取消方法,未知情况封堵失败 /*try { loadClass("com.android.server.logcat.LogcatManagerService").methodFinder().filter { name == "onLogAccessRequested" }.toList().createHooks { before { param -> XposedHelpers.callMethod(param.thisObject, "declineRequest", param.args[0]) param.result = null } } } catch (t: Throwable) { XposedLogUtils.logE(TAG, t) }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/various/NotificationBlur.java ================================================ package com.sevtinge.cemiuiler.module.hook.various; import android.graphics.drawable.Drawable; import android.view.View; import android.view.ViewGroup; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.BlurUtils; import java.lang.reflect.Field; import de.robv.android.xposed.XposedHelpers; public class NotificationBlur extends BaseHook { Class mCls = XposedHelpers.findClassIfExists("com.android.systemui.statusbar.notification.row.NotificationBackgroundView", lpparam.classLoader); Class mCls2 = XposedHelpers.findClassIfExists("com.android.systemui.statusbar.notification.policy.AppMiniWindowRowTouchHelper", lpparam.classLoader); Class mCls3 = XposedHelpers.findClassIfExists("com.android.systemui.statusbar.phone.MiuiNotificationPanelViewController", lpparam.classLoader); Class mCls4 = XposedHelpers.findClassIfExists("com.android.keyguard.magazine.LockScreenMagazineController", lpparam.classLoader); Class mCls5 = XposedHelpers.findClassIfExists("com.android.systemui.statusbar.phone.MiuiNotificationPanelViewController$mBlurRatioChangedListener$1", lpparam.classLoader); Class mCls6 = XposedHelpers.findClassIfExists("com.android.systemui.shared.plugins.PluginInstanceManager$PluginHandler", lpparam.classLoader); Class mCls7 = XposedHelpers.findClassIfExists("com.android.systemui.statusbar.notification.row.MiuiExpandableNotificationRow", lpparam.classLoader); Class mCls8 = XposedHelpers.findClassIfExists("com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout", lpparam.classLoader); @Override public void init() { hookAllMethods(mCls, "setCustomBackground", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); Field field = mCls.getDeclaredField("mDrawableAlpha"); field.setAccessible(true); field.set(param.thisObject, 200); XposedHelpers.callMethod(param.thisObject, "setDrawableAlpha", 200); } }); hookAllMethods(mCls, "draw", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); Drawable background = ((View) param.thisObject).getBackground(); if (background != null && background.getClass().getName().equals("BackgroundBlurDrawable")) { background.setBounds(((Drawable) param.args[1]).getBounds()); } } }); hookAllMethods(mCls2, "onMiniWindowTrackingStart", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { super.before(param); Field field = param.thisObject.getClass().getDeclaredField("mPickedMiniWindowChild"); field.setAccessible(true); field.get(param.thisObject); Field field2 = param.thisObject.getClass().getDeclaredField("mBackgroundNormal"); field2.setAccessible(true); field2.get(field); if (field != null && field2 != null) { View view = (View) (Object) field2; if (view.getBackground().getClass().getName().equals("BackgroundBlurDrawable")) { Drawable background = view.getBackground(); XposedHelpers.callMethod(background, "setVisible", false, false); XposedHelpers.callMethod(field2, "setDrawableAlpha", 200 + 30); } } } }); hookAllMethods(mCls3, "onStateChanged", new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); int childCount; int i = 0; Object obj = param.args[0]; int intValue = (Integer) obj; Object obj2 = param.thisObject; Object d; Field field = param.thisObject.getClass().getDeclaredField("mNotificationStackScroller"); field.setAccessible(true); field.get(obj2); d = field; ViewGroup viewGroup = (ViewGroup) d; if (intValue != 1) { int childCount2 = viewGroup.getChildCount(); if (childCount2 >= 0) { int i2 = 0; while (true) { i2++; View childAt = viewGroup.getChildAt(i2); if (childAt != null) { try { Object callMethod = XposedHelpers.callMethod(childAt, "isHeadsUpState"); if (callMethod != null) { boolean booleanValue = (Boolean) callMethod; Object callMethod2 = XposedHelpers.callMethod(childAt, "isPinned"); if (callMethod2 != null) { boolean booleanValue2 = (Boolean) callMethod2; if (!booleanValue || !booleanValue2) { /*new BlurUtils(childAt);*/ new BlurUtils(childAt, "default"); } } else { throw new NullPointerException("null cannot be cast to non-null type kotlin.Boolean"); } } else { throw new NullPointerException("null cannot be cast to non-null type kotlin.Boolean"); } } catch (Throwable ignored) { } } if (i2 == childCount2) { return; } } } } } }); hookAllMethods(mCls4, "setViewsAlpha", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { super.before(param); boolean b; Class aClass = XposedHelpers.findClassIfExists("com.android.keyguard.utils.MiuiKeyguardUtils", lpparam.classLoader); if (aClass == null) { b = true; } Object callStaticMethod = XposedHelpers.callStaticMethod(aClass, "isDefaultLockScreenTheme"); b = (Boolean) callStaticMethod; if (b) { int i = 0; float floatValue = (Float) param.args[0] * 255; Object d; Field field = param.thisObject.getClass().getDeclaredField("mNotificationStackScrollLayout"); field.setAccessible(true); field.get(param.thisObject); d = field; ViewGroup viewGroup = (ViewGroup) d; int childCount = viewGroup.getChildCount(); if (childCount >= 0) { while (true) { i++; View childAt = viewGroup.getChildAt(i); if (childAt != null) { if (floatValue >= 0 && floatValue <= 255) { if (childAt.getClass().getName().equals("ZenModeView")) { Object callMethod = XposedHelpers.callMethod(childAt, "getContentView"); if (callMethod != null) { ViewGroup viewGroup2 = (ViewGroup) callMethod; Drawable background = viewGroup.getBackground(); if (background != null && background.getClass().getName().equals("BackgroundBlurDrawable")) { XposedHelpers.callMethod(viewGroup.getBackground(), "setAlpha", i); return; } return; } return; } } } if (i == childCount) { return; } } } } } }); /*Helpers.hookAllMethods(mCls,"setHighSamplingFrequency",new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { View view = (View) param.thisObject; new BlurUtils(view); } }); Helpers.hookAllMethods(mCls2,"setCustomBackground",new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); XposedHelpers.callMethod(param.thisObject, "setDrawableAlpha", new Object[]{160}); } }); Helpers.hookAllMethods(mCls2,"draw",new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { super.after(param); Object obj = param.thisObject; Drawable background = ((View) obj).getBackground(); if (background != null) { Object obj2 = param.args[1]; background.setBounds(((Drawable) obj2).getBounds()); } } }); Helpers.hookAllMethods(mCls3,"startEnterAndLaunchMiniWindow",new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { super.before(param); Field declaredField = mCls3.getDeclaredField("mPickedMiniWindowChild"); declaredField.setAccessible(true); Object obj = declaredField.get(param.thisObject); if (obj != null) { Object callMethod = XposedHelpers.callMethod(obj, "getAnimatedBackground", new Object[0]); View view = (View) callMethod; view.setBackground(null); } } }); Class mCls5 = XposedHelpers.findClassIfExists("com.android.systemui.statusbar.notification.row.MiuiExpandableNotificationRow", lpparam.classLoader); Helpers.hookAllMethods(mCls,"updateBackgroundBg",new MethodHook() { @Override protected void after(MethodHookParam param) throws Throwable { View view = (View) XposedHelpers.getObjectField(param.thisObject,"mBackgroundNormal"); new BlurUtils(view); } });*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/various/UnlockIme.kt ================================================ package com.sevtinge.cemiuiler.module.hook.various import android.view.inputmethod.InputMethodManager import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.ClassUtils.loadClassOrNull import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.Log import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.PropertyUtils import com.sevtinge.cemiuiler.utils.api.sameAs import com.sevtinge.cemiuiler.utils.callStaticMethod import com.sevtinge.cemiuiler.utils.getObjectFieldAs import com.sevtinge.cemiuiler.utils.getStaticObjectField import com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD import com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogE import com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogI import com.sevtinge.cemiuiler.utils.setStaticObjectField import de.robv.android.xposed.callbacks.XC_LoadPackage object UnlockIme : BaseHook() { private val miuiImeList: List = listOf( "com.iflytek.inputmethod.miui", "com.sohu.inputmethod.sogou.xiaomi", "com.baidu.input_mi", "com.miui.catcherpatch" ) private var navBarColor: Int? = null override fun init() { // 检查是否支持全面屏优化 if (PropertyUtils["ro.miui.support_miui_ime_bottom", "0"] != "1") return EzXHelper.initHandleLoadPackage(lpparam) EzXHelper.setLogTag(TAG) LogI(TAG, "MiuiIme is supported") startHook(lpparam) } private fun startHook(lpparam: XC_LoadPackage.LoadPackageParam) { // 检查是否为小米定制输入法 val isNonCustomize = !miuiImeList.contains(lpparam.packageName) if (isNonCustomize) { val sInputMethodServiceInjector = loadClassOrNull("android.inputmethodservice.InputMethodServiceInjector") ?: loadClassOrNull("android.inputmethodservice.InputMethodServiceStubImpl") sInputMethodServiceInjector?.also { hookSIsImeSupport(it) hookIsXiaoAiEnable(it) setPhraseBgColor(it) } ?: LogE(TAG, "Failed:Class not found: InputMethodServiceInjector", null) } hookDeleteNotSupportIme( "android.inputmethodservice.InputMethodServiceInjector\$MiuiSwitchInputMethodListener", lpparam.classLoader ) // 获取常用语的ClassLoader loadClass("android.inputmethodservice.InputMethodModuleManager").methodFinder().filter { name == "loadDex" && parameterTypes.sameAs(ClassLoader::class.java, String::class.java) }.toList().createHooks { after { param -> hookDeleteNotSupportIme( "com.miui.inputmethod.InputMethodBottomManager\$MiuiSwitchInputMethodListener", param.args[0] as ClassLoader ) loadClassOrNull( "com.miui.inputmethod.InputMethodBottomManager", param.args[0] as ClassLoader )?.also { if (isNonCustomize) { hookSIsImeSupport(it) hookIsXiaoAiEnable(it) } // 针对A11的修复切换输入法列表 it.getMethod("getSupportIme").createHook { replace { _ -> it.getStaticObjectField("sBottomViewHelper") ?.getObjectFieldAs("mImm")?.enabledInputMethodList } } } ?: Log.e("Failed:Class not found: com.miui.inputmethod.InputMethodBottomManager") } } LogI(TAG, "Hook MIUI IME Done!") } /** * 跳过包名检查,直接开启输入法优化 * * @param clazz 声明或继承字段的类 */ private fun hookSIsImeSupport(clazz: Class<*>) { runCatching { clazz.setStaticObjectField("sIsImeSupport", 1) LogI(TAG, "Success:Hook field sIsImeSupport") }.onFailure { LogD(TAG, "Failed:Hook field sIsImeSupport ", it) } } /** * 小爱语音输入按钮失效修复 * * @param clazz 声明或继承方法的类 */ private fun hookIsXiaoAiEnable(clazz: Class<*>) { runCatching { clazz.getMethod("isXiaoAiEnable").createHook { returnConstant(false) } }.onFailure { LogD(TAG, "Failed:Hook method isXiaoAiEnable", it) } } /** * 在适当的时机修改抬高区域背景颜色 * * @param clazz 声明或继承字段的类 */ private fun setPhraseBgColor(clazz: Class<*>) { runCatching { // 导航栏颜色被设置后, 将颜色存储起来并传递给常用语 loadClass("com.android.internal.policy.PhoneWindow").methodFinder().first { name == "setNavigationBarColor" && parameterTypes.sameAs(Int::class.java) }.createHook { after { param -> if(param.args[0] == 0) return@after navBarColor = param.args[0] as Int customizeBottomViewColor(clazz) } } // 当常用语被创建后, 将背景颜色设置为存储的导航栏颜色 clazz.methodFinder().first { name == "addMiuiBottomView" }.createHook { after { customizeBottomViewColor(clazz) } } }.onFailure { LogD(TAG, "Failed to set the color of the MiuiBottomView", it) } } /** * 将导航栏颜色赋值给输入法优化的底图 * * @param clazz 声明或继承字段的类 */ private fun customizeBottomViewColor(clazz: Class<*>) { navBarColor?.let { val color = -0x1 - it clazz.callStaticMethod( "customizeBottomViewColor", true, navBarColor, color or -0x1000000, color or 0x66000000 ) } } /** * 针对A10的修复切换输入法列表 * * @param className 声明或继承方法的类的名称 */ private fun hookDeleteNotSupportIme(className: String, classLoader: ClassLoader) { runCatching { loadClass(className, classLoader).methodFinder().first { name == "deleteNotSupportIme" } .createHook { returnConstant(null) } }.onFailure { LogD(TAG, "Failed:Hook method deleteNotSupportIme", it) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/various/UnlockSuperClipboard.kt ================================================ package com.sevtinge.cemiuiler.module.hook.various import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.EzXHelper import com.github.kyuubiran.ezxhelper.EzXHelper.safeClassLoader import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHooks import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge object UnlockSuperClipboard : BaseHook() { // by StarVoyager override fun init() { when (EzXHelper.hostPackageName) { "com.miui.gallery" -> { if (mPrefsMap.getBoolean("various_super_clipboard_gallery")) { methodSuperClipboard("com.miui.gallery.util.MiscUtil") } } "com.android.fileexplorer" -> { if (mPrefsMap.getBoolean("various_super_clipboard_fileexplorer")) { methodSuperClipboard("com.android.fileexplorer.model.Util") } } "com.miui.screenshot" -> { if (mPrefsMap.getBoolean("various_super_clipboard_screenshot")) { dexKitSuperClipboard() } } "com.android.browser" -> { if (mPrefsMap.getBoolean("various_super_clipboard_browser")) { dexKitSuperClipboard() } } "com.android.mms" -> { if (mPrefsMap.getBoolean("various_super_clipboard_mms")) { dexKitSuperClipboard() } } "com.miui.notes" -> { if (mPrefsMap.getBoolean("various_super_clipboard_notes")) { methodSuperClipboard("com.miui.common.tool.Utils") } } "com.miui.creation" -> { if (mPrefsMap.getBoolean("various_super_clipboard_creation")) { methodSuperClipboard("com.miui.creation.common.tools.ClipUtils") } } } } private fun methodSuperClipboard(clsName: String) { loadClass(clsName).methodFinder() .filterByName("isSupportSuperClipboard") .first().createHook { returnConstant(true) } } private fun dexKitSuperClipboard() { val ro by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("ro.miui.support_super_clipboard") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(safeClassLoader) } val sys by lazy { dexKitBridge.findMethod { matcher { addUsingStringsEquals("persist.sys.support_super_clipboard") returnType = "boolean" } }.firstOrNull()?.getMethodInstance(safeClassLoader) } setOf(ro, sys).filterNotNull().createHooks { returnConstant(true) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/voiceassist/UseThirdPartyBrowser.kt ================================================ package com.sevtinge.cemiuiler.module.hook.voiceassist import com.sevtinge.cemiuiler.module.base.BaseHook import com.sevtinge.cemiuiler.utils.DexKit.addUsingStringsEquals import com.sevtinge.cemiuiler.utils.DexKit.dexKitBridge import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XposedBridge import java.lang.reflect.Method object UseThirdPartyBrowser : BaseHook() { private var browserActivityWithIntent: Method? = null override fun init() { dexKitBridge.findMethod { matcher { addUsingStringsEquals( "IntentUtils", "permission click No Application can handle your intent" ) } }.forEach { browserActivityWithIntent = it.getMethodInstance(lpparam.classLoader) } // XposedBridge.log("Hook到小爱同学进程!"); /*try { val result: List = java.util.Objects.requireNonNull>( VoiceAssistDexKit.mVoiceAssistResultMethodsMap["BrowserActivityWithIntent"] ) for (descriptor in result) { browserActivityWithIntent = descriptor.getMethodInstance(lpparam.classLoader) } } catch (e: Throwable) { e.printStackTrace() }*/ XposedLogUtils.logI("com.miui.voiceassist browserActivityWithIntent method is $browserActivityWithIntent") // Class clazz = XposedHelpers.findClass("e.D.L.pa.Wa", lpparam.classLoader); XposedBridge.hookMethod(browserActivityWithIntent, object : XC_MethodHook() { @Throws(Throwable::class) override fun beforeHookedMethod(param: MethodHookParam) { super.beforeHookedMethod(param) // XposedBridge.log("0)Hook到Activity启动,开始判断"); val intent = param.args[0] as android.content.Intent XposedLogUtils.logI(intent.toString()) try { if (intent.getPackage() == "com.android.browser") { XposedLogUtils.logI("com.miui.voiceassist get URL " + intent.dataString) val uri = android.net.Uri.parse(intent.dataString) val newIntent = android.content.Intent() newIntent.setAction("android.intent.action.VIEW") newIntent.setData(uri) param.args[0] = newIntent } } catch (e: Exception) { XposedLogUtils.logE(TAG, e) } } }) } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/module/hook/weather/SetDeviceLevel.java ================================================ package com.sevtinge.cemiuiler.module.hook.weather; import static com.sevtinge.cemiuiler.utils.Helpers.getPackageVersionCode; import android.content.Context; import android.os.Bundle; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.PrefsUtils; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XC_MethodReplacement; public class SetDeviceLevel extends BaseHook { Class mUtil; @Override public void init() { if (getPackageVersionCode(lpparam) < 15000000) mUtil = findClassIfExists("miuix.animation.utils.DeviceUtils") ; else mUtil = findClassIfExists("d7.a"); returnIntConstant(mUtil); } public static Bundle checkBundle(Context context, Bundle bundle) { if (context == null) { XposedLogUtils.logI("SetWeatherDeviceLevel", "Context is null!"); return null; } if (bundle == null) bundle = new Bundle(); int order = Integer.parseInt(PrefsUtils.getSharedStringPrefs(context, "weather_device_level", "0")); bundle.putInt("current_sory_type", order - 1); bundle.putInt("current_sort_type", order - 1); return bundle; } private void returnIntConstant(Class cls) { int order = mPrefsMap.getStringAsInt("weather_device_level", 0); if (getPackageVersionCode(lpparam) < 15000000) hookAllMethods(cls, "transDeviceLevel", XC_MethodReplacement.returnConstant(order)); else findAndHookMethod(cls, "j", XC_MethodReplacement.returnConstant(order)); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/prefs/PreferenceHeader.java ================================================ package com.sevtinge.cemiuiler.prefs; import android.content.Context; import android.util.AttributeSet; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.sevtinge.cemiuiler.R; import moralnorm.preference.Preference; public class PreferenceHeader extends Preference { public PreferenceHeader(@NonNull Context context) { super(context); init(); } public PreferenceHeader(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } private void init() { setLayoutResource(R.layout.preference_header); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/provider/SharedPrefsProvider.java ================================================ package com.sevtinge.cemiuiler.provider; import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; import android.content.SharedPreferences; import android.content.UriMatcher; import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.util.Log; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.PrefsUtils; import java.io.File; import java.io.FileNotFoundException; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; public class SharedPrefsProvider extends ContentProvider { public static final String AUTHORITY = "com.sevtinge.cemiuiler.provider.sharedprefs"; private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); SharedPreferences prefs; static { uriMatcher.addURI(AUTHORITY, "string/*/", 0); uriMatcher.addURI(AUTHORITY, "string/*/*", 1); uriMatcher.addURI(AUTHORITY, "integer/*/*", 2); uriMatcher.addURI(AUTHORITY, "boolean/*/*", 3); uriMatcher.addURI(AUTHORITY, "stringset/*", 4); uriMatcher.addURI(AUTHORITY, "test/*", 5); uriMatcher.addURI(AUTHORITY, "shortcut_icon/*", 6); } @Override public boolean onCreate() { try { prefs = PrefsUtils.getSharedPrefs(getContext(), true); return true; } catch (Throwable throwable) { return false; } } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { List parts = uri.getPathSegments(); // Log.e("parts", String.valueOf(parts)); MatrixCursor cursor = new MatrixCursor(new String[]{"data"}); switch (uriMatcher.match(uri)) { case 0 -> { cursor.newRow().add("data", prefs.getString(parts.get(1), "")); return cursor; } case 1 -> { cursor.newRow().add("data", prefs.getString(parts.get(1), parts.get(2))); return cursor; } case 2 -> { cursor.newRow().add("data", prefs.getInt(parts.get(1), Integer.parseInt(parts.get(2)))); return cursor; } case 3 -> { cursor.newRow().add("data", prefs.getBoolean(parts.get(1), Integer.parseInt(parts.get(2)) == 1) ? 1 : 0); return cursor; } case 4 -> { Set strings = prefs.getStringSet(parts.get(1), new LinkedHashSet<>()); for (String str : strings) cursor.newRow().add("data", str); return cursor; } } return null; } @Override public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { if (getContext() == null) return null; List parts = uri.getPathSegments(); if (uriMatcher.match(uri) == 5) { String filename = null; if ("0".equals(parts.get(1))) filename = "test0.png"; else if ("1".equals(parts.get(1))) filename = "test1.mp3"; else if ("2".equals(parts.get(1))) filename = "test2.mp4"; else if ("3".equals(parts.get(1)) || "5".equals(parts.get(1))) filename = "test3.txt"; else if ("4".equals(parts.get(1))) filename = "test4.zip"; AssetFileDescriptor afd = null; if (filename != null) try { afd = getContext().getAssets().openFd(filename); } catch (Throwable t) { Log.i("afd", String.valueOf(t)); } return afd; } else if (uriMatcher.match(uri) == 6) { Context context = Helpers.getProtectedContext(getContext()); File file = new File(context.getFilesDir() + "/shortcuts/" + parts.get(1) + "_shortcut.png"); if (!file.exists()) return null; return new AssetFileDescriptor(ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY), 0, AssetFileDescriptor.UNKNOWN_LENGTH); } return null; } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/CustomHookActivity.java ================================================ package com.sevtinge.cemiuiler.ui; import android.content.Intent; import android.os.Bundle; import android.widget.Button; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.customhook.CustomHookConfigActivity; import moralnorm.appcompat.app.AppCompatActivity; public class CustomHookActivity extends AppCompatActivity { Button mAddConfig; @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(R.layout.activity_custom_hook); initView(); } private void initView() { mAddConfig = findViewById(R.id.add_config); mAddConfig.setOnClickListener(v -> startActivity(new Intent(this, CustomHookConfigActivity.class))); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/HideAppActivity.java ================================================ package com.sevtinge.cemiuiler.ui; import moralnorm.appcompat.app.AppCompatActivity; public class HideAppActivity extends AppCompatActivity { } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/MainActivity.java ================================================ package com.sevtinge.cemiuiler.ui; import android.annotation.SuppressLint; import android.app.backup.BackupManager; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.os.FileObserver; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.ActionMode; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.TextView; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.data.adapter.ModSearchAdapter; import com.sevtinge.cemiuiler.provider.SharedPrefsProvider; import com.sevtinge.cemiuiler.ui.base.SettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.AboutFragment; import com.sevtinge.cemiuiler.ui.fragment.MainFragment; import com.sevtinge.cemiuiler.utils.CtaUtils; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.PrefsUtils; import com.sevtinge.cemiuiler.utils.SearchHelper; import com.sevtinge.cemiuiler.utils.SettingLauncherHelper; import com.sevtinge.cemiuiler.utils.ShellUtils; import com.sevtinge.cemiuiler.view.RestartAlertDialog; import java.util.Set; import moralnorm.view.SearchActionMode; public class MainActivity extends SettingsActivity { View mFrameContent; View mSearchView; SearchActionMode mSearchActionMode; TextView mSearchInputView; RecyclerView mSearchResultView; TextWatcher mSearchResultListener; ModSearchAdapter mSearchAdapter; String lastFilter; String mPermission = "Cemiuiler_Permission"; private final MainFragment mMainFrag = new MainFragment(); private final int REQUEST_CODE = 2038; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState == null) requestCta(); new Thread(new Runnable() { public void run() { SearchHelper.getAllMods(MainActivity.this, savedInstanceState != null); } }).start(); initView(); initData(); setImmersionMenuEnabled(true); setFragment(mMainFrag); ShellUtils.execCommand("chmod 0777 " + getPackageCodePath() + " ; chmod 0777 " + PrefsUtils.mPrefsFile + " ; chown root:root " + PrefsUtils.mPrefsFile, true, false); // ShellUtils.execCommand("chmod 0777 " + PrefsUtils.mPrefsFile, true, false); // ShellUtils.execCommand("chown root:root " + PrefsUtils.mPrefsFile, true, false); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); requestCta(); } private void requestCta() { if (!CtaUtils.isCtaEnabled(this)) { CtaUtils.showCtaDialog(this, REQUEST_CODE); } } private void initView() { mFrameContent = findViewById(R.id.frame_content); mSearchView = findViewById(R.id.search_view); mSearchInputView = findViewById(android.R.id.input); mSearchResultView = findViewById(R.id.search_result_view); mSearchAdapter = new ModSearchAdapter(); mSearchInputView.setHint(getResources().getString(R.string.search)); mSearchResultView.setLayoutManager(new LinearLayoutManager(this)); mSearchResultView.setAdapter(mSearchAdapter); mSearchView.setOnClickListener(v -> startSearchMode()); mSearchAdapter.setOnItemClickListener((view, ad) -> { SettingLauncherHelper.onStartSettingsForArguments(this, SubSettings.class, ad.fragment, null, ad.catTitleResId); }); mSearchResultListener = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { findMod(s.toString()); } @Override public void afterTextChanged(Editable s) { findMod(s.toString()); } }; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); if (itemId == R.id.restart) { RestartAlertDialog dialog = new RestartAlertDialog(this); dialog.setTitle(item.getTitle()); dialog.show(); } else if (itemId == R.id.settings) { Intent intent = new Intent(this, ModuleSettingsActivity.class); startActivity(intent); } else if (itemId == R.id.about) { SettingLauncherHelper.onStartSettings(this, SubSettings.class, AboutFragment.class, item.getTitle().toString()); } return super.onOptionsItemSelected(item); } private void initData() { SharedPreferences.OnSharedPreferenceChangeListener mPreferenceChangeListener = (sharedPreferences, s) -> { Log.i("prefs", "Changed: " + s); requestBackup(); Object val = sharedPreferences.getAll().get(s); String path = ""; if (val instanceof String) path = "string/"; else if (val instanceof Set) path = "stringset/"; else if (val instanceof Integer) path = "integer/"; else if (val instanceof Boolean) path = "boolean/"; getContentResolver().notifyChange(Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/" + path + s), null); if (!"".equals(path)) getContentResolver().notifyChange(Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/pref/" + path + s), null); }; PrefsUtils.mSharedPreferences.registerOnSharedPreferenceChangeListener(mPreferenceChangeListener); Helpers.fixPermissionsAsync(getApplicationContext()); try { FileObserver mFileObserver = new FileObserver(PrefsUtils.getSharedPrefsPath(), FileObserver.CLOSE_WRITE) { @Override public void onEvent(int event, String path) { Helpers.fixPermissionsAsync(getApplicationContext()); } }; mFileObserver.startWatching(); } catch (Throwable t) { Log.e("prefs", "Failed to start FileObserver!"); } } void findMod(String filter) { lastFilter = filter; mSearchResultView.setVisibility("".equals(filter) ? View.GONE : View.VISIBLE); ModSearchAdapter adapter = (ModSearchAdapter) mSearchResultView.getAdapter(); if (adapter == null) return; adapter.getFilter().filter(filter); } private void startSearchMode() { mFrameContent.setVisibility(View.GONE); SearchActionMode startActionMode = (SearchActionMode) startActionMode(new SearchActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode actionMode, Menu menu) { SearchActionMode searchActionMode = (SearchActionMode) actionMode; searchActionMode.setAnchorView(mSearchView); searchActionMode.setAnimateView(findViewById(android.R.id.list_container)); searchActionMode.getSearchInput().addTextChangedListener(mSearchResultListener); return true; } @Override public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) { return true; } @Override public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) { return true; } @Override public void onDestroyActionMode(ActionMode actionMode) { SearchActionMode searchActionMode = (SearchActionMode) actionMode; searchActionMode.getSearchInput().removeTextChangedListener(mSearchResultListener); exitSearchMode(); updateData(); } }); if (startActionMode == null) { throw new NullPointerException("null cannot be cast to non-null type moralnorm.appcompat.internal.view.SearchActionMode"); } mSearchActionMode = startActionMode; } private void exitSearchMode() { if (mSearchActionMode != null) { mSearchActionMode = null; } mFrameContent.setVisibility(View.VISIBLE); } public void requestBackup() { new BackupManager(getApplicationContext()).dataChanged(); } private void updateData() { mFrameContent.setVisibility(View.VISIBLE); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (requestCode == REQUEST_CODE) { if (resultCode == RESULT_CANCELED) { finish(); } else if (resultCode == RESULT_FIRST_USER) { CtaUtils.setCtaEnabled(this); } } super.onActivityResult(requestCode, resultCode, data); } /** * @noinspection deprecation */ private boolean PermissionRecord(boolean iNeedGet) { @SuppressLint({"WorldWriteableFiles", "WorldReadableFiles"}) SharedPreferences sharedPreferences = getSharedPreferences(mPermission, MODE_WORLD_WRITEABLE | MODE_WORLD_READABLE); if (!iNeedGet) { boolean mPermissionRecord = sharedPreferences.getBoolean("mPermissionRecord", false); /* 需要每次更新软件重新弹出界面可以使用下面的方法 String PackageCodePath = sharedPreferences.getString("mPackageCodePath", "null"); String Now_PackageCodePath = getPackageCodePath(); if (!hasExecutedCommand || !PackageCodePath.equals(Now_PackageCodePath)) { */ if (!mPermissionRecord) { // 标记得到允许 SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putBoolean("mPermissionRecord", true); /*editor.putString("packageCodePath", Now_PackageCodePath);*/ editor.apply(); } } return sharedPreferences.getBoolean("mPermissionRecord", false); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/ModuleSettingsActivity.java ================================================ package com.sevtinge.cemiuiler.ui; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.widget.Toast; import androidx.annotation.Nullable; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.SettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.ModuleSettingsFragment; import com.sevtinge.cemiuiler.utils.BackupUtils; import com.sevtinge.cemiuiler.utils.Helpers; import moralnorm.appcompat.app.AlertDialog; public class ModuleSettingsActivity extends SettingsActivity { ModuleSettingsFragment mModuleSettingsFragment = new ModuleSettingsFragment(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setFragment(mModuleSettingsFragment); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (grantResults.length == 0) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); return; } switch (requestCode) { case Helpers.REQUEST_PERMISSIONS_BACKUP -> { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { mModuleSettingsFragment.backupSettings(this); } else if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Toast.makeText(this, R.string.backup_ask, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, R.string.backup_permission, Toast.LENGTH_LONG).show(); } } case Helpers.REQUEST_PERMISSIONS_RESTORE -> { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { mModuleSettingsFragment.restoreSettings(this); } else if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Toast.makeText(this, R.string.rest_ask, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, R.string.rest_permission, Toast.LENGTH_LONG).show(); } } default -> super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (data == null) return; try { AlertDialog.Builder alert = new AlertDialog.Builder(this); switch (requestCode) { case BackupUtils.CREATE_DOCUMENT_CODE -> { BackupUtils.handleCreateDocument(this, data.getData()); alert.setTitle(R.string.backup_success); } case BackupUtils.OPEN_DOCUMENT_CODE -> { BackupUtils.handleReadDocument(this, data.getData()); alert.setTitle(R.string.rest_success); } default -> { return; } } alert.setPositiveButton(android.R.string.ok, (dialog, which) -> { }); alert.show(); } catch (Exception e) { AlertDialog.Builder alert = new AlertDialog.Builder(this); switch (requestCode) { case BackupUtils.CREATE_DOCUMENT_CODE -> alert.setTitle(R.string.backup_failed); case BackupUtils.OPEN_DOCUMENT_CODE -> alert.setTitle(R.string.rest_failed); } alert.setMessage(e.toString()); alert.setPositiveButton(android.R.string.ok, (dialog, which) -> { }); alert.show(); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/SubPickerActivity.java ================================================ package com.sevtinge.cemiuiler.ui; import android.content.Intent; import android.os.Bundle; import com.sevtinge.cemiuiler.callback.IAppSelectCallback; import com.sevtinge.cemiuiler.ui.base.SettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.sub.AppPicker; public class SubPickerActivity extends SettingsActivity { AppPicker mAppSelectFragment = new AppPicker(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAppSelectFragment.setAppSelectCallback(new IAppSelectCallback() { @Override public void sendMsgToActivity(byte[] appIcon, String appName, String appPackageName, String appVersion, String appActivityName) { Intent intent = new Intent(); intent.putExtra("appIcon", appIcon); intent.putExtra("appName", appName); intent.putExtra("appPackageName", appPackageName); intent.putExtra("appVersion", appVersion); intent.putExtra("appActivityName", appActivityName); setResult(1, intent); } @Override public String getMsgFromActivity(String s) { return null; } }); setFragment(mAppSelectFragment); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/SubSettings.java ================================================ package com.sevtinge.cemiuiler.ui; import com.sevtinge.cemiuiler.ui.base.SettingsActivity; public class SubSettings extends SettingsActivity {} ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/base/BaseSettingsActivity.java ================================================ package com.sevtinge.cemiuiler.ui.base; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.ImageView; import androidx.fragment.app.Fragment; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.MainActivity; import com.sevtinge.cemiuiler.utils.Helpers; import com.sevtinge.cemiuiler.utils.ShellUtils; import com.sevtinge.cemiuiler.utils.log.AndroidLogUtils; import java.util.ArrayList; import java.util.List; import moralnorm.appcompat.app.ActionBar; import moralnorm.appcompat.app.AlertDialog; import moralnorm.appcompat.app.AppCompatActivity; public class BaseSettingsActivity extends AppCompatActivity { private String initialFragmentName; public BaseSettingsProxy mProxy; public ActionBar mActionBar; public static List mActivityList = new ArrayList<>(); @Override public void onCreate(Bundle savedInstanceState) { Intent intent = getIntent(); mProxy = new SettingsProxy(this); initialFragmentName = mProxy.getInitialFragmentName(intent); if (TextUtils.isEmpty(initialFragmentName)) { initialFragmentName = intent.getStringExtra(":android:show_fragment"); } super.onCreate(savedInstanceState); createUiFromIntent(savedInstanceState, intent); } protected void createUiFromIntent(Bundle savedInstanceState, Intent intent) { mProxy.setupContentView(); initActionBar(); mActivityList.add(this); Fragment targetFragment = mProxy.getTargetFragment(this, initialFragmentName, savedInstanceState); if (targetFragment != null) { targetFragment.setArguments(mProxy.getArguments(intent)); setFragment(targetFragment); } if (!(this instanceof MainActivity)) { findViewById(R.id.search_view).setVisibility(View.GONE); } showXposedActiveDialog(); } private void initActionBar() { setDisplayHomeAsUpEnabled(); } private void setDisplayHomeAsUpEnabled() { if (this instanceof MainActivity) { getAppCompatActionBar().setDisplayHomeAsUpEnabled(false); } } public void setActionBarEndView(View view) { getAppCompatActionBar().setEndView(view); } public void setRestartView(View.OnClickListener l) { if (l != null) { ImageView mRestartView = new ImageView(this); mRestartView.setImageResource(R.drawable.ic_reboot_small); mRestartView.setOnClickListener(l); setActionBarEndView(mRestartView); } } public void showRestartSystemDialog() { showRestartDialog(true, "", ""); } public void showRestartDialog(String appLabel, String packageName) { showRestartDialog(false, appLabel, packageName); } public void showRestartDialog(boolean isRestartSystem, String appLabel, String packageName) { String isSystem = getResources().getString(R.string.restart_app_desc, appLabel); String isOther = getResources().getString(R.string.restart_app_desc, " " + appLabel + " "); new AlertDialog.Builder(this) .setCancelable(false) .setTitle(getResources().getString(R.string.soft_reboot) + " " + appLabel) .setMessage(isRestartSystem ? isSystem : isOther) .setHapticFeedbackEnabled(true) .setPositiveButton(android.R.string.ok, (dialog, which) -> doRestart(packageName, isRestartSystem)) .setNegativeButton(android.R.string.cancel, null) .show(); } public void showXposedActiveDialog() { if (!Helpers.isModuleActive) { new AlertDialog.Builder(this) .setCancelable(false) .setTitle(R.string.tip) .setMessage(R.string.hook_failed) .setHapticFeedbackEnabled(true) .setPositiveButton(android.R.string.ok, null) .show(); } } public void setFragment(Fragment fragment) { getSupportFragmentManager() .beginTransaction() .replace(R.id.frame_content, fragment) .commit(); } public void doRestart(String packageName, boolean isRestartSystem) { boolean result = false; boolean pid = true; if (isRestartSystem) { result = ShellUtils.getResultBoolean("reboot", true); } else { if (packageName != null) { ShellUtils.CommandResult commandResult = ShellUtils.execCommand("{ [[ $(pgrep -f '" + packageName + "' | grep -v $$) != \"\" ]] && { pkill -l 9 -f \"" + packageName + "\"; }; } || { echo \"kill error\"; }", true, true); if (commandResult.result == 0) { if ("kill error".equals(commandResult.successMsg)) { pid = false; } else result = true; } else AndroidLogUtils.LogE("doRestart: ", "result: " + commandResult.result + " errorMsg: " + commandResult.errorMsg, null); } else { AndroidLogUtils.LogE("doRestart: ", "packageName is null", null); } // result = ShellUtils.getResultBoolean("pkill -l 9 -f " + packageName, true); } if (!result) { new AlertDialog.Builder(this) .setCancelable(false) .setTitle(R.string.tip) .setMessage(isRestartSystem ? R.string.reboot_failed : pid ? R.string.kill_failed : R.string.pid_failed) .setHapticFeedbackEnabled(true) .setPositiveButton(android.R.string.ok, null) .show(); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/base/BaseSettingsProxy.java ================================================ package com.sevtinge.cemiuiler.ui.base; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import androidx.fragment.app.Fragment; import moralnorm.appcompat.app.AppCompatActivity; import moralnorm.preference.Preference; public abstract class BaseSettingsProxy { AppCompatActivity mActivity; public abstract void setupContentView(); public abstract void handleIntent(Intent intent); public abstract void initView(Bundle bundle); public abstract boolean onBackPressed(); public abstract void onCreateOptionsMenu(Menu menu); public abstract void onDestroyView(); public abstract void onOptionsItemSelected(MenuItem menuItem); public abstract void onPause(); public abstract void onPrepareOptionsMenu(Menu menu); public abstract void onResume(); public abstract String getInitialFragmentName(Intent intent); public abstract Fragment getTargetFragment(Context context, String initialFragmentName, Bundle savedInstanceState); public abstract Bundle getArguments(Intent intent); public abstract void onStartSettingsForArguments(Class cls, Preference preference, boolean isEnableBundle); } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/base/SettingsActivity.java ================================================ package com.sevtinge.cemiuiler.ui.base; import androidx.annotation.NonNull; import com.sevtinge.cemiuiler.ui.SubSettings; import com.sevtinge.cemiuiler.ui.fragment.framework.OtherSettings; import com.sevtinge.cemiuiler.ui.fragment.home.HomeDockSettings; import com.sevtinge.cemiuiler.ui.fragment.home.HomeFolderSettings; import com.sevtinge.cemiuiler.ui.fragment.home.HomeGestureSettings; import com.sevtinge.cemiuiler.ui.fragment.sub.MultiActionSettings; import com.sevtinge.cemiuiler.ui.fragment.various.AlertDialogSettings; import moralnorm.preference.Preference; import moralnorm.preference.PreferenceFragmentCompat; import moralnorm.preference.compat.PreferenceFragment; public class SettingsActivity extends BaseSettingsActivity implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { public void onStartSettingsForArguments(Preference preference, boolean isBundleEnable) { mProxy.onStartSettingsForArguments(SubSettings.class, preference, isBundleEnable); } @Override public boolean onPreferenceStartFragment(@NonNull PreferenceFragmentCompat preferenceFragmentCompat, @NonNull Preference preference) { boolean isBundleEnable = preferenceFragmentCompat instanceof OtherSettings || preferenceFragmentCompat instanceof HomeDockSettings || preferenceFragmentCompat instanceof HomeFolderSettings || preferenceFragmentCompat instanceof AlertDialogSettings || preferenceFragmentCompat instanceof HomeGestureSettings || preferenceFragmentCompat instanceof MultiActionSettings; onStartSettingsForArguments(preference, isBundleEnable); return true; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/base/SettingsProxy.java ================================================ package com.sevtinge.cemiuiler.ui.base; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.utils.SettingLauncherHelper; import moralnorm.appcompat.app.AppCompatActivity; import moralnorm.preference.Preference; public class SettingsProxy extends BaseSettingsProxy { public FragmentManager mFragmentManager; public SettingsProxy(AppCompatActivity activity) { mActivity = activity; } private void replaceFragment(Fragment fragment, String tag) { mFragmentManager.beginTransaction().replace(R.id.frame_content, fragment, tag).commit(); } @Override public void setupContentView() { mActivity.setContentView(R.layout.settings_main); } @Override public void handleIntent(Intent intent) { } @Override public void initView(Bundle bundle) { mFragmentManager = mActivity.getSupportFragmentManager(); } @Override public boolean onBackPressed() { return false; } @Override public void onCreateOptionsMenu(Menu menu) { } @Override public void onDestroyView() { } @Override public void onOptionsItemSelected(MenuItem menuItem) { } @Override public void onPause() { } @Override public void onPrepareOptionsMenu(Menu menu) { } @Override public void onResume() { } @Override public String getInitialFragmentName(Intent intent) { return intent.getStringExtra(":settings:show_fragment"); } @Override public Fragment getTargetFragment(Context context, String initialFragmentName, Bundle savedInstanceState) { try { return Fragment.instantiate(context, initialFragmentName, savedInstanceState); } catch (Exception e) { Log.e("Settings", "Unable to get target fragment", e); return null; } } @Override public Bundle getArguments(Intent intent) { Bundle args = intent.getBundleExtra(":settings:show_fragment_args"); String showFragmentTitle = intent.getStringExtra(":settings:show_fragment_title"); int showFragmentTitleResId = intent.getIntExtra(":settings:show_fragment_title_resid", 0); args.putString(":fragment:show_title", showFragmentTitle); args.putInt(":fragment:show_title_resid", showFragmentTitleResId); return args; } @Override public void onStartSettingsForArguments(Class cls, Preference preference, boolean isEnableBundle) { Bundle args = null; if (isEnableBundle) { args = new Bundle(); args.putString("key", preference.getKey()); } String mFragmentName = preference.getFragment(); String mTitle = preference.getTitle().toString(); SettingLauncherHelper.onStartSettingsForArguments(mActivity, cls, mFragmentName, args, mTitle); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/customhook/CustomHookConfigActivity.java ================================================ package com.sevtinge.cemiuiler.ui.customhook; import android.os.Bundle; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.SettingsActivity; public class CustomHookConfigActivity extends SettingsActivity { @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(R.layout.activity_custom_hook_config); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/AboutFragment.kt ================================================ package com.sevtinge.cemiuiler.ui.fragment import android.content.Intent import android.net.Uri import com.sevtinge.cemiuiler.BuildConfig import com.sevtinge.cemiuiler.R import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment import com.sevtinge.hyperceiler.expansionpacks.utils.ClickCountsUtils; import moralnorm.preference.Preference import moralnorm.preference.SwitchPreference import java.util.Calendar import kotlin.math.abs class AboutFragment : SettingsPreferenceFragment() { private var lIIlIll = 100 ushr 7 private val lIIlIlI = 100 ushr 6 override fun getContentResId(): Int { return R.xml.prefs_about } override fun initPrefs() { val lIIlllI = ClickCountsUtils.getClickCounts() val lIIllII = findPreference("prefs_key_various_enable_super_function") val mQQGroup = findPreference("prefs_key_about_join_qq_group") lIIllII?.title = BuildConfig.VERSION_NAME + " | " + BuildConfig.BUILD_TYPE lIIllII?.onPreferenceClickListener = Preference.OnPreferenceClickListener { lIIllll-> if (BuildConfig.BUILD_TYPE.contains("debug")) lIIllII?.title = BuildConfig.VERSION_NAME + " | " + BuildConfig.BUILD_TYPE + " | $lIIlllI" lIIllll as SwitchPreference lIIllll.isChecked = !(lIIllll.isChecked) lIIlIll++ if (BuildConfig.BUILD_TYPE.contains("debug")) lIIllII?.title = BuildConfig.VERSION_NAME + " | " + BuildConfig.BUILD_TYPE + " | $lIIlIll/$lIIlllI" if (lIIllll.isChecked) { if (lIIlIll >= lIIlIlI) { lIIllll.isChecked = !(lIIllll.isChecked) if (BuildConfig.BUILD_TYPE.contains("debug")) lIIllII?.title = BuildConfig.VERSION_NAME + " | " + BuildConfig.BUILD_TYPE + " | HF OFF" lIIlIll = 100 ushr 8 } } else if (lIIlIll >= lIIlllI) { lIIllll.isChecked = !(lIIllll.isChecked) if (BuildConfig.BUILD_TYPE.contains("debug")) lIIllII?.title = BuildConfig.VERSION_NAME + " | " + BuildConfig.BUILD_TYPE + " | HF ON" lIIlIll = 100 ushr 8 } false } mQQGroup?.onPreferenceClickListener = Preference.OnPreferenceClickListener { "MF68KGcOGYEfMvkV_htdyT6D6C13We_r".joinQQGroup() //&authKey=du488g%2FRPdQ%2FaUq0IKuDLvK24mEmbpRidqHGE6qqv3wpa1lbUa6Vi7JJ4YxWe7s5&noverify=0&group_code=247909573 true } } /** * 调用 joinQQGroup() 即可发起手Q客户端申请加群 * @param this@joinQQGroup 由官网生成的key * @return 返回true表示呼起手Q成功,返回false表示呼起失败 */ private fun String.joinQQGroup(): Boolean { val intent = Intent() intent.data = 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${this}") // https://jq.qq.com/?_wv=1027&k=EsyE1RhL // 此Flag可根据具体产品需要自定义,如设置,则在加群界面按返回,返回手Q主界面,不设置,按返回会返回到呼起产品界面 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) return try { startActivity(intent) true } catch (e: Exception) { // 未安装手Q或安装的版本不支持 false } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/AiAsstFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class AiAsstFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.aiasst; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.aiasst), "com.xiaomi.aiasst.vision" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/AodFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class AodFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.aod; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.aod), "com.miui.aod" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/BarrageFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class BarrageFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.barrage; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.barrage), "com.xiaomi.barrage" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/BrowserFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class BrowserFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.browser; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.browser), "com.android.browser" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/CameraFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class CameraFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.camera; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.camera), "com.android.camera" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/ClockFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class ClockFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.clock; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.clock), "com.android.deskclock" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/ContentExtensionFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.SwitchPreference; public class ContentExtensionFragment extends SettingsPreferenceFragment { SwitchPreference mUnlockTaplus; @Override public int getContentResId() { return R.xml.content_extension; } @Override public void initPrefs() { mUnlockTaplus= findPreference("prefs_key_content_extension_unlock_taplus"); mUnlockTaplus.setVisible(!isAndroidR()); } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.content_extension), "com.miui.contentextension" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/CreationFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class CreationFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.creation; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.creation), "com.miui.creation" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/DownloadsFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class DownloadsFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.downloads; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.downloads), "com.android.providers.downloads.ui" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/FileExplorerFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class FileExplorerFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.fileexplorer; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.fileexplorer), "com.android.fileexplorer" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/GalleryFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class GalleryFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.gallery; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.gallery), "com.miui.gallery" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/GuardProviderFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class GuardProviderFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.guard_provider; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.guard_provider), "com.miui.guardprovider" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/HomeFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/InCallUiFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class InCallUiFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.incallui; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.incallui), "com.android.incallui" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/JoyoseFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class JoyoseFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.joyose; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.joyose), "com.xiaomi.joyose" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/LbeFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class LbeFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.lbe_security; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.lbe), "com.lbe.security.miui" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MainFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import java.util.Random; import moralnorm.preference.Preference; public class MainFragment extends SettingsPreferenceFragment { Preference mPowerSetting; Preference mMTB; Preference mSecurityCenter; Preference mSecurityCenterPad; Preference mTip; Random r = new Random(); int[] tips = new int[]{ R.string.tip_0, R.string.tip_1, R.string.tip_2, R.string.tip_3, R.string.tip_4, R.string.tip_5, R.string.tip_6, R.string.tip_7, R.string.tip_8, R.string.tip_9, R.string.tip_10, R.string.tip_11, R.string.tip_12, R.string.tip_13, R.string.tip_14, R.string.tip_15, R.string.tip_16, R.string.tip_17, R.string.tip_18, R.string.tip_19, R.string.tip_20, }; @Override public int getContentResId() { return R.xml.prefs_main; } @Override public void initPrefs() { int randomTip = r.nextInt(tips.length); // log("tip id is" + randomTip); mPowerSetting = findPreference("prefs_key_powerkeeper"); mMTB = findPreference("prefs_key_mtb"); mSecurityCenter = findPreference("prefs_key_security_center"); mSecurityCenterPad = findPreference("prefs_key_security_center_pad"); mTip = findPreference("prefs_key_tip"); mPowerSetting.setVisible(!isAndroidR()); mMTB.setVisible(!isAndroidR()); mSecurityCenter.setVisible(!isPad()); mSecurityCenterPad.setVisible(isPad()); mTip.setSummary(tips[randomTip]); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MarketFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MarketFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.market; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.market), "com.xiaomi.market" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MediaEditorFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MediaEditorFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.mediaeditor; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.mediaeditor), "com.miui.mediaeditor" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MiLinkFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MiLinkFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.milink; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.milink), "com.milink.service" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MiSettingsFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MiSettingsFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.mi_settings; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.mi_settings), "com.xiaomi.misettings" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MiShareFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.SwitchPreference; public class MiShareFragment extends SettingsPreferenceFragment { SwitchPreference mMiShareNotAuto; @Override public int getContentResId() { return R.xml.mishare; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.mishare), "com.miui.mishare.connectivity" ); } @Override public void initPrefs() { mMiShareNotAuto = findPreference("prefs_key_disable_mishare_auto_off"); /*int appVersionCode = getPackageVersionCode(lpparam); if (appVersionCode <= 21400) { mMiShareNotAuto.setSummary(R.string.app_version_not_supported); mMiShareNotAuto.setEnabled(false); }*/ } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MiWallpaperFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MiWallpaperFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.miwallpaper; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartSystemDialog(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MirrorFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MirrorFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.mirror; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.mirror), "com.xiaomi.mirror" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MiuiPackageInstallerFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MiuiPackageInstallerFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.package_installer; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.package_installer), "com.miui.packageinstaller" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MmsFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MmsFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.mms; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.mms), "com.android.mms" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/ModuleSettingsFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.app.Activity; import android.content.ComponentName; import android.content.pm.PackageManager; import android.widget.Toast; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.HideAppActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.BackupUtils; import com.sevtinge.cemiuiler.utils.DialogHelper; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.appcompat.app.AppCompatActivity; import moralnorm.preference.DropDownPreference; import moralnorm.preference.MultiSelectListPreference; import moralnorm.preference.Preference; import moralnorm.preference.SwitchPreference; public class ModuleSettingsFragment extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener { MultiSelectListPreference mReboot; DropDownPreference mIconModePreference; DropDownPreference mIconModeValue; @Override public int getContentResId() { return R.xml.prefs_settings; } @Override public void initPrefs() { int mIconMode = Integer.parseInt(PrefsUtils.getSharedStringPrefs(getContext(), "prefs_key_settings_icon", "0")); mIconModePreference = findPreference("prefs_key_settings_icon"); mIconModeValue = findPreference("prefs_key_settings_icon_mode"); SwitchPreference mHideAppIcon = findPreference("prefs_key_settings_hide_app_icon"); setIconMode(mIconMode); mIconModePreference.setOnPreferenceChangeListener(this); mHideAppIcon.setOnPreferenceChangeListener((preference, o) -> { PackageManager pm = getActivity().getPackageManager(); int mComponentEnabledState; if ((Boolean) o) { mComponentEnabledState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED; } else { mComponentEnabledState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED; } pm.setComponentEnabledSetting(new ComponentName(getActivity(), HideAppActivity.class), mComponentEnabledState, PackageManager.DONT_KILL_APP); return true; }); mReboot = findPreference("prefs_key_settings_reboot"); mReboot.setVisible(false); /*String[] mRestartAllScopes = getResources().getStringArray(R.array.xposed_scope); List mItemList = Arrays.asList(mRestartAllScopes); String[] mItems = new String[0]; if (mItemList.contains("android")) { List mItemList2 = new ArrayList<>(mItemList); mItemList2.remove("android"); mItems = mItemList2.toArray(new String[mItemList2.size()]); } mReboot = findPreference("prefs_key_settings_reboot"); mReboot.setEntries(mItems); mReboot.setEntryValues(mItems); mReboot.setOnPreferenceChangeListener((preference, o) -> { List mShellPackageName = new ArrayList<>(); CharSequence[] extras = mReboot.getEntries(); Set options = (Set) o; for (String op : options) { int index = mReboot.findIndexOfValue(op); mShellPackageName.add("killall " + extras[index]); Toast.makeText(getActivity(), "killall " + extras[index], Toast.LENGTH_SHORT).show(); } ShellUtils.execCommand(mShellPackageName, true); return false; });*/ findPreference("prefs_key_back").setOnPreferenceClickListener(preference -> { final AppCompatActivity activity = (AppCompatActivity) getActivity(); backupSettings(activity); return true; }); findPreference("prefs_key_rest").setOnPreferenceClickListener(preference -> { restoreSettings(getActivity()); return true; }); findPreference("prefs_key_reset").setOnPreferenceClickListener(preference -> { DialogHelper.showDialog(getActivity(), R.string.reset_title, R.string.reset_desc, (dialog, which) -> { PrefsUtils.mSharedPreferences.edit().clear().apply(); Toast.makeText(getActivity(), R.string.reset_okay, Toast.LENGTH_LONG).show(); }); return true; }); } @Override public boolean onPreferenceChange(Preference preference, Object o) { if (preference == mIconModePreference) { setIconMode(Integer.parseInt((String) o)); } return true; } private void setIconMode(int mode) { mIconModeValue.setVisible(mode != 0); } public void backupSettings(Activity activity) { BackupUtils.backup(activity); } public void restoreSettings(Activity activity) { BackupUtils.restore(activity); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MtbFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MtbFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.mtb; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.mtb), "com.xiaomi.mtb" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/MusicFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MusicFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.music; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.music), "com.miui.player" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/NetworkBoostFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class NetworkBoostFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.networkboost; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.networkboost), "com.xiaomi.networkboost" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/NfcFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class NfcFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.nfc; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.nfc), "com.android.nfc" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/PersonalAssistantFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.ColorPickerPreference; import moralnorm.preference.DropDownPreference; import moralnorm.preference.Preference; import moralnorm.preference.SeekBarPreferenceEx; import moralnorm.preference.SwitchPreference; public class PersonalAssistantFragment extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener { SwitchPreference mWidgetCrack; SwitchPreference mBlurBackground; SeekBarPreferenceEx mBlurRadius; ColorPickerPreference mBlurColor; DropDownPreference mBlurBackgroundStyle; @Override public int getContentResId() { return R.xml.personal_assistant; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.personal_assistant), "com.miui.personalassistant" ); } @Override public void initPrefs() { int mBlurMode = Integer.parseInt(PrefsUtils.getSharedStringPrefs(getContext(), "prefs_key_personal_assistant_value", "1")); mWidgetCrack = findPreference("prefs_key_personal_assistant_widget_crack"); mBlurBackground = findPreference("prefs_key_pa_enable"); mBlurBackgroundStyle = findPreference("prefs_key_personal_assistant_value"); mBlurRadius = findPreference("prefs_key_personal_assistant_blurradius"); mBlurColor = findPreference("prefs_key_personal_assistant_color"); mBlurBackground.setVisible(!isAndroidR()); // 负一屏背景设置 if (!getSharedPreferences().getBoolean("prefs_key_various_enable_super_function", false)) { mWidgetCrack.setVisible(false); } setBlurMode(mBlurMode); mBlurBackgroundStyle.setOnPreferenceChangeListener(this); } @Override public boolean onPreferenceChange(Preference preference, Object o) { if (preference == mBlurBackgroundStyle) { setBlurMode(Integer.parseInt((String) o)); } return true; } private void setBlurMode(int mode) { mBlurRadius.setVisible(mode == 2); mBlurColor.setVisible(mode == 2); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/PhoneFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class PhoneFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.phone; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.phone), "com.android.phone" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/PowerKeeperFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class PowerKeeperFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.powerkeeper; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.powerkeeper), "com.miui.powerkeeper" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/ScannerFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class ScannerFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.scanner; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.scanner), "com.xiaomi.scanner" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/ScreenRecorderFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class ScreenRecorderFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.screenrecorder; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.screenrecorder), "com.miui.screenrecorder" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/ScreenShotFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class ScreenShotFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.screenshot; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.screenshot), "com.miui.screenshot" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/SecurityCenterFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import android.Manifest; import android.provider.Settings; import android.view.View; import androidx.core.app.ActivityCompat; import androidx.core.content.PermissionChecker; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.Preference; import moralnorm.preference.SwitchPreference; public class SecurityCenterFragment extends SettingsPreferenceFragment { String mSecurity; SwitchPreference mAiClipboard; SwitchPreference mBlurLocation; Preference mNewboxBackgroundCustom; SwitchPreference mOpenByDefaultSetting; SwitchPreference mSecurityBackground; SwitchPreference mSecurityColor; @Override public int getContentResId() { return R.xml.security_center; } @Override public View.OnClickListener addRestartListener() { mSecurity = getResources().getString(!isPad() ? R.string.security_center : R.string.security_center_pad); return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( mSecurity, "com.miui.securitycenter" ); } @Override public void initPrefs() { int permission = ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_SECURE_SETTINGS); mBlurLocation = findPreference("prefs_key_security_center_blur_location"); mAiClipboard = findPreference("prefs_key_security_center_ai_clipboard"); mOpenByDefaultSetting = findPreference("prefs_key_security_center_app_default_setting"); mSecurityColor = findPreference("prefs_key_security_center_sidebar_line_color"); mSecurityBackground = findPreference("prefs_key_se_enable"); mNewboxBackgroundCustom = findPreference("prefs_key_security_center_newbox_bg_custom"); if (permission != PermissionChecker.PERMISSION_GRANTED) { mBlurLocation.setSummary(R.string.security_center_no_permission); mAiClipboard.setSummary(R.string.security_center_no_permission); mBlurLocation.setEnabled(false); mAiClipboard.setEnabled(false); } else { boolean mBlurLocationEnable = Settings.Secure.getInt(getContext().getContentResolver(), "mi_lab_blur_location_enable", 0) == 1; boolean mAiClipboardEnable = Settings.Secure.getInt(getContext().getContentResolver(), "mi_lab_ai_clipboard_enable", 0) == 1; mBlurLocation.setChecked(mBlurLocationEnable); mAiClipboard.setChecked(mAiClipboardEnable); } mSecurityColor.setVisible(!isAndroidR()); // 侧滑栏提示线自定义 mSecurityBackground.setVisible(!isAndroidR()); // 侧滑栏背景自定义 mOpenByDefaultSetting.setVisible(!isAndroidR()); // 应用打开链接管理 boolean mBlurLocationEnable = Settings.Secure.getInt(getContext().getContentResolver(), "mi_lab_blur_location_enable", 0) == 1; boolean mAiClipboardEnable = Settings.Secure.getInt(getContext().getContentResolver(), "mi_lab_ai_clipboard_enable", 0) == 1; mBlurLocation.setChecked(mBlurLocationEnable); mAiClipboard.setChecked(mAiClipboardEnable); mBlurLocation.setOnPreferenceChangeListener((preference, o) -> { Settings.Secure.putInt(getContext().getContentResolver(), "mi_lab_blur_location_enable", (Boolean) o ? 1 : 0); return true; }); mAiClipboard.setOnPreferenceChangeListener((preference, o) -> { Settings.Secure.putInt(getContext().getContentResolver(), "mi_lab_ai_clipboard_enable", (Boolean) o ? 1 : 0); return true; }); } @Override public boolean onPreferenceTreeClick(Preference preference) { if (preference == mNewboxBackgroundCustom) { /*openMultiAction(preference, null, PickerHomeActivity.Actions.Blur);*/ } return super.onPreferenceTreeClick(preference); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/SystemFrameworkFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import miui.telephony.TelephonyManager; import moralnorm.preference.Preference; import moralnorm.preference.SwitchPreference; public class SystemFrameworkFragment extends SettingsPreferenceFragment { SwitchPreference mDisableCreak; SwitchPreference mDisableIntegrity; Preference mNetwork; @Override public int getContentResId() { return R.xml.framework; } @Override public void initPrefs() { boolean mCreak = PrefsUtils.getSharedBoolPrefs(getContext(), "prefs_key_system_framework_core_patch_auth_creak", false); mDisableCreak = findPreference("prefs_key_system_framework_core_patch_auth_creak"); mDisableIntegrity = findPreference("prefs_key_system_framework_core_patch_disable_integrity"); mNetwork = findPreference("prefs_key_system_framework_network"); mDisableIntegrity.setVisible(isMoreAndroidVersion(33) && !mCreak); mNetwork.setVisible(TelephonyManager.getDefault().isFiveGCapable()); mDisableCreak.setOnPreferenceChangeListener((preference, o) -> { if ((boolean) o) { mDisableIntegrity.setChecked(false); mDisableIntegrity.setVisible(false); } else { mDisableIntegrity.setVisible(isMoreAndroidVersion(33)); } return true; }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/SystemSettingsFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreMiuiVersion; import android.provider.Settings; import android.view.View; import android.widget.SeekBar; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.log.AndroidLogUtils; import moralnorm.preference.PreferenceCategory; import moralnorm.preference.SeekBarPreferenceEx; import moralnorm.preference.SwitchPreference; public class SystemSettingsFragment extends SettingsPreferenceFragment { PreferenceCategory mNewNfc; // 新版 NFC 界面 PreferenceCategory mAreaScreenshot; // 区域截屏 SwitchPreference mHighMode; // 极致模式 SwitchPreference mNoveltyHaptic; // 新版触感调节页面 SwitchPreference mPad; // 解锁平板分区 @Override public int getContentResId() { return R.xml.system_settings; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity) getActivity()).showRestartDialog( getResources().getString(R.string.system_settings), "com.android.settings" ); } @Override public void initPrefs() { mHighMode = findPreference("prefs_key_system_settings_develop_speed_mode"); mAreaScreenshot = findPreference("prefs_key_system_settings_accessibility"); mNewNfc = findPreference("prefs_key_system_settings_connection_sharing"); mNoveltyHaptic = findPreference("prefs_key_system_settings_novelty_haptic"); mPad = findPreference("prefs_key_system_settings_enable_pad_area"); mHighMode.setVisible(!isAndroidR()); mAreaScreenshot.setVisible(isAndroidR()); mNewNfc.setVisible(isMoreMiuiVersion(14f) && isMoreAndroidVersion(33)); mNoveltyHaptic.setVisible(isMoreMiuiVersion(14f) && isMoreAndroidVersion(31)); mPad.setVisible(isPad()); animationScale(); } public void animationScale() { SeekBarPreferenceEx seekBarPreferenceWn = findPreference("prefs_key_system_settings_window_animation_scale"); setOnSeekBarChangeListener(seekBarPreferenceWn, "window_animation_scale"); SeekBarPreferenceEx seekBarPreferenceTr = findPreference("prefs_key_system_settings_transition_animation_scale"); setOnSeekBarChangeListener(seekBarPreferenceTr, "transition_animation_scale"); SeekBarPreferenceEx seekBarPreferenceAn = findPreference("prefs_key_system_settings_animator_duration_scale"); setOnSeekBarChangeListener(seekBarPreferenceAn, "animator_duration_scale"); } public void setOnSeekBarChangeListener(SeekBarPreferenceEx mySeekBarPreference, String name) { mySeekBarPreference.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { setAnimator(progress, name); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); } public void setAnimator(int i, String name) { float mFloat = ((float) i) / 100; try { Settings.Global.putFloat(getContext().getContentResolver(), name, mFloat); } catch (Throwable e) { AndroidLogUtils.LogE("setAnimator", "set: " + name + " float: " + mFloat, e); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/SystemUIFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class SystemUIFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.system_ui; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/ThemeManagerFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreMiuiVersion; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.PreferenceCategory; import moralnorm.preference.SwitchPreference; public class ThemeManagerFragment extends SettingsPreferenceFragment { PreferenceCategory mVersionCodeModifyPreferenceCat; SwitchPreference mVersionCodeModifyPreference; SwitchPreference mThemeManagerCrack; @Override public int getContentResId() { return R.xml.theme_manager; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.theme_manager), "com.android.thememanager" ); } @Override public void initPrefs() { mVersionCodeModifyPreferenceCat = findPreference("prefs_key_theme_manager_version_code_modify_cat"); mVersionCodeModifyPreference = findPreference("prefs_key_theme_manager_version_code_modify"); if (!isMoreMiuiVersion(13f)) { mVersionCodeModifyPreferenceCat.setVisible(true); } else { mVersionCodeModifyPreferenceCat.setVisible(false); mVersionCodeModifyPreference.setChecked(false); mVersionCodeModifyPreference.setEnabled(false); } mThemeManagerCrack = findPreference("prefs_key_various_theme_crack"); if (!getSharedPreferences().getBoolean("prefs_key_various_enable_super_function", false)) { mThemeManagerCrack.setVisible(false); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/TsmClientFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class TsmClientFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.tsmclient; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.tsmclient), "com.miui.tsmclient" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/UpdaterFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import androidx.annotation.NonNull; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.DropDownPreference; import moralnorm.preference.EditTextPreference; import moralnorm.preference.Preference; public class UpdaterFragment extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener { DropDownPreference mUpdateMode; EditTextPreference mBigVersion; @Override public int getContentResId() { return R.xml.updater; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.updater), "com.android.updater" ); } @Override public void initPrefs() { int mMode = Integer.parseInt(PrefsUtils.getSharedStringPrefs(getContext(), "prefs_key_updater_version_mode", "1")); mUpdateMode = findPreference("prefs_key_updater_version_mode"); mBigVersion = findPreference("prefs_key_various_updater_big_version"); setMode(mMode); mUpdateMode.setOnPreferenceChangeListener(this); } @Override public boolean onPreferenceChange(@NonNull Preference preference, Object o) { if (preference == mUpdateMode) { setMode(Integer.parseInt((String) o)); } return true; } private void setMode(int mode) { mBigVersion.setVisible(mode == 2); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/VariousFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidT; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreMiuiVersion; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.Preference; import moralnorm.preference.SwitchPreference; public class VariousFragment extends SettingsPreferenceFragment { SwitchPreference mDisableBluetoothRestrict; // 禁用蓝牙临时关闭 SwitchPreference mDisableDeviceLog; // 关闭访问设备日志确认 Preference mMipad; // 平板相关功能 @Override public int getContentResId() { return R.xml.various; } @Override public void initPrefs() { mDisableBluetoothRestrict = findPreference("prefs_key_various_disable_bluetooth_restrict"); mDisableDeviceLog = findPreference("prefs_key_various_disable_access_device_logs"); mMipad = findPreference("prefs_key_various_mipad"); mDisableBluetoothRestrict.setVisible(isMoreMiuiVersion(14f) && isMoreAndroidVersion(31)); mDisableDeviceLog.setVisible(isAndroidT()); mMipad.setVisible(isPad()); mDisableBluetoothRestrict.setOnPreferenceChangeListener((preference, o) -> true); mDisableDeviceLog.setOnPreferenceChangeListener((preference, o) -> true); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/WeatherFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class WeatherFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.weather; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.weather), "com.miui.weather2" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/about/AboutContributerFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.about; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class AboutContributerFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.prefs_about_contributor; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/about/AboutUseFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.about; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class AboutUseFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.prefs_about_use; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/base/BasePreferenceFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.base; import android.content.Context; import android.os.Bundle; import android.text.TextUtils; import androidx.fragment.app.Fragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.Preference; import moralnorm.preference.PreferenceManager; import moralnorm.preference.compat.PreferenceFragment; public class BasePreferenceFragment extends PreferenceFragment { private PreferenceManager mPreferenceManager; @Override public void onCreatePreferences(Bundle bundle, String s) { mPreferenceManager = getPreferenceManager(); mPreferenceManager.setSharedPreferencesName(PrefsUtils.mPrefsName); mPreferenceManager.setSharedPreferencesMode(Context.MODE_PRIVATE); mPreferenceManager.setStorageDeviceProtected(); } public void setTitle(int titleResId) { setTitle(getResources().getString(titleResId)); } public void setTitle(String title) { if (!TextUtils.isEmpty(title)) { getActivity().setTitle(title); } } public String getFragmentName(Fragment fragment) { return fragment.getClass().getName(); } public String getPreferenceTitle(Preference preference) { return preference.getTitle().toString(); } public String getPreferenceKey(Preference preference) { return preference.getKey(); } public void finish() { getActivity().finish(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/base/SettingsPreferenceFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.base; import android.content.SharedPreferences; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.utils.PrefsUtils; public abstract class SettingsPreferenceFragment extends BasePreferenceFragment { public String mTitle; public int mContentResId = 0; public int mTitleResId = 0; @Override public void onCreatePreferences(Bundle bundle, String s) { super.onCreatePreferences(bundle, s); Bundle args = getArguments(); if (args != null) { mTitle = args.getString(":fragment:show_title"); mTitleResId = args.getInt(":fragment:show_title_resid"); mContentResId = args.getInt("contentResId"); } if (mTitleResId != 0) setTitle(mTitleResId); if (!TextUtils.isEmpty(mTitle)) setTitle(mTitle); mContentResId = mContentResId != 0 ? mContentResId : getContentResId(); if (mContentResId != 0) { setPreferencesFromResource(mContentResId, s); initPrefs(); } ((BaseSettingsActivity)getActivity()).setRestartView(addRestartListener()); } public View.OnClickListener addRestartListener() { return null; } public SharedPreferences getSharedPreferences() { return PrefsUtils.mSharedPreferences; } public boolean hasKey(String key) { return getSharedPreferences().contains(key); } public void initPrefs() {} public abstract int getContentResId(); } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/framework/DisplaySettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.framework; import android.view.View; import android.widget.SeekBar; import com.sevtinge.cemiuiler.R; import moralnorm.preference.SeekBarPreferenceEx; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class DisplaySettings extends SettingsPreferenceFragment { SeekBarPreferenceEx minBrightness; SeekBarPreferenceEx maxBrightness; @Override public int getContentResId() { return R.xml.framework_display; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartSystemDialog(); } @Override public void initPrefs() { maxBrightness = findPreference("pref_key_system_ui_auto_brightness_max"); minBrightness = findPreference("pref_key_system_ui_auto_brightness_min"); assert minBrightness != null; minBrightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (!fromUser) return; if (maxBrightness.getValue() <= progress) maxBrightness.setValue(progress + 1); maxBrightness.setMinValue(progress + 1); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/framework/FreeFormSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.framework; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreMiuiVersion; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.PreferenceCategory; import moralnorm.preference.SwitchPreference; public class FreeFormSettings extends SettingsPreferenceFragment { SwitchPreference mMoreFreeForm; // 多小窗 PreferenceCategory mSmallFreeForm; // 小窗气泡 @Override public int getContentResId() { return R.xml.framework_freeform; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartSystemDialog(); } @Override public void initPrefs() { mMoreFreeForm = findPreference("prefs_key_system_framework_freeform_count"); mSmallFreeForm = findPreference("prefs_key_system_framework_freeform_bubble_title"); mMoreFreeForm.setVisible(isMoreMiuiVersion(13f)); mSmallFreeForm.setVisible(!isAndroidR()); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/framework/NetworkSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.framework; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class NetworkSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.framework_phone; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartSystemDialog(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/framework/OtherSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.framework; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidT; import android.content.Intent; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.SubPickerActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.Preference; import moralnorm.preference.SwitchPreference; public class OtherSettings extends SettingsPreferenceFragment { Preference mCleanShareApps; Preference mCleanOpenApps; SwitchPreference mAppLinkVerify; SwitchPreference mUseOriginalAnim; @Override public int getContentResId() { return R.xml.framework_other; } @Override public void initPrefs() { mCleanShareApps = findPreference("prefs_key_system_framework_clean_share_apps"); mCleanOpenApps = findPreference("prefs_key_system_framework_clean_open_apps"); mAppLinkVerify = findPreference("prefs_key_system_framework_disable_app_link_verify"); mAppLinkVerify.setVisible(!isAndroidR()); mAppLinkVerify.setOnPreferenceChangeListener((preference, o) -> true); mUseOriginalAnim = findPreference("prefs_key_system_framework_other_use_original_animation"); mUseOriginalAnim.setVisible(!isAndroidT()); mCleanShareApps.setOnPreferenceClickListener(preference -> { Intent intent = new Intent(getActivity(), SubPickerActivity.class); intent.putExtra("is_app_selector", false); intent.putExtra("key", preference.getKey()); startActivity(intent); return true; }); mCleanOpenApps.setOnPreferenceClickListener(preference -> { Intent intent = new Intent(getActivity(), SubPickerActivity.class); intent.putExtra("is_app_selector", false); intent.putExtra("key", preference.getKey()); startActivity(intent); return true; }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/framework/VolumeSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.framework; import android.provider.Settings; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.DropDownPreference; public class VolumeSettings extends SettingsPreferenceFragment { DropDownPreference mDefaultVolumeStream; @Override public int getContentResId() { return R.xml.framework_volume; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartSystemDialog(); } @Override public void initPrefs() { mDefaultVolumeStream = findPreference("prefs_key_system_framework_default_volume_stream"); mDefaultVolumeStream.setOnPreferenceChangeListener((preference, o) -> { Settings.Secure.putInt(getContext().getContentResolver(), "system_framework_default_volume_stream", Integer.parseInt((String) o)); return true; }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeDockSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.os.Build; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.SwitchPreference; public class HomeDockSettings extends SettingsPreferenceFragment { SwitchPreference mDisableRecentIcon; SwitchPreference mDockBackground; @Override public int getContentResId() { return R.xml.home_dock; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } @Override public void initPrefs() { mDisableRecentIcon = findPreference("prefs_key_home_dock_disable_recents_icon"); mDockBackground = findPreference("prefs_key_home_dock_bg_custom_enable"); mDisableRecentIcon.setVisible(isPad()); mDockBackground.setVisible(isMoreAndroidVersion(Build.VERSION_CODES.S)); mDockBackground.setEnabled(mDockBackground.isVisible()); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeDrawerSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.SwitchPreference; public class HomeDrawerSettings extends SettingsPreferenceFragment { SwitchPreference mAllAppsContainerViewBlur; @Override public int getContentResId() { return R.xml.home_drawer; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } @Override public void initPrefs() { mAllAppsContainerViewBlur = findPreference("prefs_key_home_drawer_blur"); mAllAppsContainerViewBlur.setVisible(!isAndroidR()); mAllAppsContainerViewBlur.setOnPreferenceChangeListener((preference, o) -> true); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeFolderSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.os.Build; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.DropDownPreference; import moralnorm.preference.Preference; import moralnorm.preference.SeekBarPreferenceEx; import moralnorm.preference.SwitchPreference; public class HomeFolderSettings extends SettingsPreferenceFragment { DropDownPreference mFolderShade; SeekBarPreferenceEx mFolderShadeLevel; SeekBarPreferenceEx mFolderColumns; SwitchPreference mFolderWidth; SwitchPreference mFolderSpace; Preference mSmallFolderIconBackgroundCustom; Preference mSmallFolderIconBackgroundCustom1; Preference mSmallFolderIconBackgroundCustom2; Preference mSmallFolderIconBackgroundCustom3; @Override public int getContentResId() { return R.xml.home_folder; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } @Override public void initPrefs() { mFolderShade = findPreference("prefs_key_home_folder_shade"); mFolderShadeLevel = findPreference("prefs_key_home_folder_shade_level"); mFolderColumns = findPreference("prefs_key_home_folder_columns"); mFolderWidth = findPreference("prefs_key_home_folder_width"); mFolderSpace = findPreference("prefs_key_home_folder_space"); mSmallFolderIconBackgroundCustom = findPreference("prefs_key_home_small_folder_icon_bg_custom"); if (mSmallFolderIconBackgroundCustom != null) { mSmallFolderIconBackgroundCustom.setVisible(isMoreAndroidVersion(Build.VERSION_CODES.S)); mSmallFolderIconBackgroundCustom.setEnabled(mSmallFolderIconBackgroundCustom.isVisible()); } mSmallFolderIconBackgroundCustom1 = findPreference("prefs_key_home_big_folder_icon_bg_2x1"); if (mSmallFolderIconBackgroundCustom1 != null) { mSmallFolderIconBackgroundCustom1.setVisible(isMoreAndroidVersion(Build.VERSION_CODES.S)); mSmallFolderIconBackgroundCustom1.setEnabled(mSmallFolderIconBackgroundCustom1.isVisible()); } mSmallFolderIconBackgroundCustom2 = findPreference("prefs_key_home_big_folder_icon_bg_1x2"); if (mSmallFolderIconBackgroundCustom2 != null) { mSmallFolderIconBackgroundCustom2.setVisible(isMoreAndroidVersion(Build.VERSION_CODES.S)); mSmallFolderIconBackgroundCustom2.setEnabled(mSmallFolderIconBackgroundCustom2.isVisible()); } mSmallFolderIconBackgroundCustom3 = findPreference("prefs_key_home_big_folder_icon_bg"); if (mSmallFolderIconBackgroundCustom3 != null) { mSmallFolderIconBackgroundCustom3.setVisible(isMoreAndroidVersion(Build.VERSION_CODES.S)); mSmallFolderIconBackgroundCustom3.setEnabled(mSmallFolderIconBackgroundCustom3.isVisible()); } setBigFolderTextForPad(); setFolderShadeLevelEnable(Integer.parseInt(PrefsUtils.mSharedPreferences.getString("prefs_key_home_folder_shade", "0"))); setFolderWidthEnable(PrefsUtils.mSharedPreferences.getInt(mFolderColumns.getKey(), 3)); setFolderSpaceEnable(PrefsUtils.mSharedPreferences.getInt(mFolderColumns.getKey(), 3)); mFolderShade.setOnPreferenceChangeListener((preference, o) -> { setFolderShadeLevelEnable(Integer.parseInt((String) o)); return true; }); mFolderColumns.setOnPreferenceChangeListener(((preference, o) -> { setFolderWidthEnable((Integer) o); setFolderSpaceEnable((Integer) o); return true; })); } private void setBigFolderTextForPad(){ if (isPad()){ mSmallFolderIconBackgroundCustom1.setTitle(R.string.home_big_folder_icon_bg_2x1_n); mSmallFolderIconBackgroundCustom2.setTitle(R.string.home_big_folder_icon_bg_1x2_n); mSmallFolderIconBackgroundCustom3.setTitle(R.string.home_big_folder_icon_bg_n); } } private void setFolderShadeLevelEnable(int i) { boolean isEnable = i != 0; mFolderShadeLevel.setVisible(isEnable); mFolderShadeLevel.setEnabled(isEnable); } private void setFolderWidthEnable(int columns) { boolean isEnable = columns > 1; mFolderWidth.setVisible(isEnable); mFolderWidth.setEnabled(isEnable); } private void setFolderSpaceEnable(int columns) { boolean isEnable = columns > 3; mFolderSpace.setVisible(isEnable); mFolderSpace.setEnabled(isEnable); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeGestureSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeGestureSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_gesture; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeLayoutSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeLayoutSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_layout; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeOtherSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidT; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.SwitchPreference; public class HomeOtherSettings extends SettingsPreferenceFragment { SwitchPreference mFixAndroidRS; SwitchPreference mEnableMoreSettings; SwitchPreference mEnableFold; @Override public int getContentResId() { return R.xml.home_other; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } @Override public void initPrefs() { mFixAndroidRS = findPreference("prefs_key_home_other_fix_android_r_s"); mEnableMoreSettings = findPreference("prefs_key_home_other_mi_pad_enable_more_setting"); mEnableFold = findPreference("prefs_key_personal_assistant_overlap_mode"); mFixAndroidRS.setVisible(!isAndroidT()); mEnableMoreSettings.setVisible(isPad()); mEnableFold.setVisible(!isAndroidR()); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeRecentSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.SwitchPreference; public class HomeRecentSettings extends SettingsPreferenceFragment { SwitchPreference mShowMenInfo; SwitchPreference mHideCleanIcon; SwitchPreference mNotHideCleanIcon; @Override public int getContentResId() { return R.xml.home_recent; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } @Override public void initPrefs() { mShowMenInfo = findPreference("prefs_key_home_recent_show_memory_info"); mHideCleanIcon = findPreference("prefs_key_home_recent_hide_clean_up"); mNotHideCleanIcon = findPreference("prefs_key_always_show_clean_up"); mShowMenInfo.setVisible(isPad()); mHideCleanIcon.setOnPreferenceChangeListener((preference, o) -> { if (!(boolean) o) { mNotHideCleanIcon.setChecked(false); } return true; }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeTitleAnimSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeTitleAnimSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_title_anim; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeTitleSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.SwitchPreference; public class HomeTitleSettings extends SettingsPreferenceFragment { SwitchPreference mDisableMonoChrome; SwitchPreference mDisableMonetColor; SwitchPreference mDisableHideTheme; @Override public int getContentResId() { return R.xml.home_title; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } @Override public void initPrefs() { mDisableMonoChrome = findPreference("prefs_key_home_other_icon_mono_chrome"); mDisableMonoChrome.setVisible(isMoreAndroidVersion(33)); mDisableMonoChrome.setOnPreferenceChangeListener((preference, o) -> true); mDisableMonetColor = findPreference("prefs_key_home_other_icon_monet_color"); mDisableMonetColor.setVisible(isMoreAndroidVersion(33)); mDisableMonetColor.setOnPreferenceChangeListener((preference, o) -> true); mDisableHideTheme = findPreference("prefs_key_home_title_disable_hide_theme"); mDisableHideTheme.setVisible(isPad()); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/HomeWidgetSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeWidgetSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_widget; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/anim/HomeTitleAnim1Settings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home.anim; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeTitleAnim1Settings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_title_anim_1; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/anim/HomeTitleAnim2Settings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home.anim; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeTitleAnim2Settings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_title_anim_2; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/anim/HomeTitleAnim3Settings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home.anim; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeTitleAnim3Settings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_title_anim_3; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/anim/HomeTitleAnim4Settings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home.anim; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeTitleAnim4Settings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_title_anim_4; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/anim/HomeTitleAnim5Settings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home.anim; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeTitleAnim5Settings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_title_anim_5; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/anim/HomeTitleAnim6Settings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home.anim; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeTitleAnim6Settings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_title_anim_6; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/anim/HomeTitleAnim7Settings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home.anim; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeTitleAnim7Settings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_title_anim_7; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/home/anim/HomeTitleAnim8Settings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.home.anim; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class HomeTitleAnim8Settings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.home_title_anim_8; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.home), "com.miui.home" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/settings/SafeModeFragment.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.settings; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class SafeModeFragment extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.settings_safe_mode; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/sub/AppPicker.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.sub; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.ProgressBar; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.callback.IAppSelectCallback; import com.sevtinge.cemiuiler.data.AppData; import com.sevtinge.cemiuiler.data.adapter.AppDataAdapter; import com.sevtinge.cemiuiler.provider.SharedPrefsProvider; import com.sevtinge.cemiuiler.utils.BitmapUtils; import com.sevtinge.cemiuiler.utils.PrefsUtils; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; public class AppPicker extends Fragment { private Bundle args; private String key = null; private boolean appSelector; private View mRootView; private ProgressBar mAmProgress; private RecyclerView mAppListRv; private AppDataAdapter mAppListAdapter; private List appDataList; public Handler mHandler; private Set selectedApps; private IAppSelectCallback mAppSelectCallback; public void setAppSelectCallback(IAppSelectCallback callback) { mAppSelectCallback = callback; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mRootView = inflater.inflate(R.layout.fragment_app_picker, container, false); initView(); return mRootView; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requireActivity().setTitle(R.string.array_global_actions_launch_choose); args = requireActivity().getIntent().getExtras(); assert args != null; appSelector = args.getBoolean("is_app_selector"); if (appSelector) { key = args.getString("app_selector_key"); } else { key = args.getString("key"); } initData(); } private void initView() { mAmProgress = mRootView.findViewById(R.id.am_progressBar); mAppListRv = mRootView.findViewById(R.id.app_list_rv); mAppListRv.setLayoutManager(new LinearLayoutManager(getContext())); mAppListAdapter = new AppDataAdapter(getActivity(), key, appSelector ? 1 : 0); mHandler = new Handler(); mAppListAdapter.setOnItemClickListener((view, position, appData, isCheck) -> { if (appSelector) { mAppSelectCallback.sendMsgToActivity(BitmapUtils.Bitmap2Bytes(appData.icon), appData.label, appData.packageName, appData.versionName + "(" + appData.versionCode + ")", appData.activityName); requireActivity().finish(); } else { CheckBox checkBox = view.findViewById(android.R.id.checkbox); // String key = "prefs_key_system_framework_clean_share_apps"; selectedApps = new LinkedHashSet<>(PrefsUtils.mSharedPreferences.getStringSet(key, new LinkedHashSet<>())); if (checkBox.isChecked()) { checkBox.setChecked(false); selectedApps.remove(appData.packageName); } else { checkBox.setChecked(true); selectedApps.add(appData.packageName); } PrefsUtils.mSharedPreferences.edit().putStringSet(key, selectedApps).apply(); } }); } private void initData() { new Thread(new Runnable() { @Override public void run() { appDataList = getAppInfo(getContext()); mHandler.post(new Runnable() { @Override public void run() { mAppListRv.setAdapter(mAppListAdapter); mAppListAdapter.setData(appDataList); mAmProgress.setVisibility(View.INVISIBLE); mAppListRv.setVisibility(View.VISIBLE); } }); } }).start(); } /** * 该方法提供了用于判断一个程序是系统程序还是用户程序的功能。 * * @param applicationInfo * @return true 用户自己安装的软件 * fasle 系统软件. */ public static boolean filterApp(ApplicationInfo applicationInfo) { if ((applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) { return true; } else if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { return true; } return false; } public void getOpenWithApps(Context context, List appInfoList) { PackageManager pm = context.getPackageManager(); Intent mainIntent = new Intent(); mainIntent.setAction(Intent.ACTION_VIEW); mainIntent.setDataAndType(Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/test/5"), "*/*"); mainIntent.putExtra("Cemiuiler", true); List packs = pm.queryIntentActivities(mainIntent, PackageManager.MATCH_ALL | PackageManager.MATCH_DISABLED_COMPONENTS); mainIntent = new Intent(); mainIntent.setAction(Intent.ACTION_VIEW); mainIntent.setData(Uri.parse("https://home.miui.com/")); mainIntent.putExtra("Cemiuiler", true); List packs2 = pm.queryIntentActivities(mainIntent, PackageManager.MATCH_ALL); mainIntent = new Intent(); mainIntent.setAction(Intent.ACTION_VIEW); mainIntent.setData(Uri.parse("vnd.youtube:n9AcG0glVu4")); mainIntent.putExtra("Cemiuiler", true); List packs3 = pm.queryIntentActivities(mainIntent, PackageManager.MATCH_ALL); mainIntent = new Intent(); mainIntent.setAction(Intent.ACTION_SEND); mainIntent.putExtra(Intent.EXTRA_TEXT, "Cemiuiler is the best!"); mainIntent.setType("*/*"); List packs4 = pm.queryIntentActivities(mainIntent, PackageManager.MATCH_ALL); packs.addAll(packs2); packs.addAll(packs3); packs.addAll(packs4); AppData app; for (ResolveInfo pack : packs) try { boolean exists = false; for (AppData openWithApp : appInfoList) { if (openWithApp.packageName.equals(pack.activityInfo.applicationInfo.packageName)) { exists = true; break; } } if (exists) { continue; } app = new AppData(); app.icon = BitmapUtils.drawableToBitmap(pack.activityInfo.applicationInfo.loadIcon(pm)); app.packageName = pack.activityInfo.applicationInfo.packageName; app.enabled = pack.activityInfo.applicationInfo.enabled; app.label = pack.activityInfo.applicationInfo.loadLabel(pm).toString(); appInfoList.add(app); } catch (Throwable e) { e.printStackTrace(); } } public List getAppInfo(Context context) { List appDataList = new ArrayList<>(); if (appSelector) { getAppSelector(context, appDataList); } else { getOpenWithApps(context, appDataList); } return appDataList; } public void getAppSelector(Context context, List appInfoList) { PackageManager packageManager = context.getPackageManager(); Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); List resolveInfos = packageManager.queryIntentActivities(mainIntent, 0); AppData appData; for (ResolveInfo resolveInfo : resolveInfos) { appData = new AppData(); appData.icon = BitmapUtils.drawableToBitmap(resolveInfo.loadIcon(packageManager)); appData.label = resolveInfo.loadLabel(packageManager).toString(); appData.packageName = resolveInfo.activityInfo.packageName; appData.activityName = resolveInfo.activityInfo.name; appData.enabled = resolveInfo.activityInfo.enabled; appInfoList.add(appData); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/sub/CustomBackgroundSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.sub; import android.os.Bundle; import android.widget.Toast; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.ColorPickerPreference; import moralnorm.preference.Preference; import moralnorm.preference.SeekBarPreference; import moralnorm.preference.SwitchPreference; public class CustomBackgroundSettings extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener { private String mKey = ""; private String mCustomBackgroundEnabledKey; private String mColorKey; private String mCornerRadiusKey; private String mBlurEnabledKey; private String mBlurRadiusKey; private SwitchPreference mCustomEnabledPreference; private ColorPickerPreference mColorPickerPreference; private SeekBarPreference mCornerRadiusPreference; private SwitchPreference mBlurEnabledPreference; private SeekBarPreference mBlurRadiusPreference; @Override public int getContentResId() { return R.xml.custom_background; } @Override public void initPrefs() { Bundle args = getArguments(); if (args != null) { mKey = args.getString("key"); mCustomBackgroundEnabledKey = mKey + "_custom_enable"; mColorKey = mKey + "_color"; mCornerRadiusKey = mKey + "_corner_radius"; mBlurEnabledKey = mKey + "_blur_enabled"; mBlurRadiusKey = mKey + "_blur_radius"; } else { finish(); } mCustomEnabledPreference = findPreference("prefs_key_custom_background_enabled"); mColorPickerPreference = findPreference("prefs_key_custom_background_color"); mCornerRadiusPreference = findPreference("prefs_key_custom_background_corner_radius"); mBlurEnabledPreference = findPreference("prefs_key_custom_background_blur_enabled"); mBlurRadiusPreference = findPreference("prefs_key_custom_background_blur_radius"); loadData(); mCustomEnabledPreference.setOnPreferenceChangeListener(this); mColorPickerPreference.setOnPreferenceChangeListener(this); mCornerRadiusPreference.setOnPreferenceChangeListener(this); mBlurEnabledPreference.setOnPreferenceChangeListener(this); mBlurRadiusPreference.setOnPreferenceChangeListener(this); } private void loadData() { mCustomEnabledPreference.setChecked(isCustomEnabled()); mColorPickerPreference.setColor(getColor(-1)); mCornerRadiusPreference.setValue(getSeekBarValue(mCornerRadiusKey, 18)); mBlurEnabledPreference.setChecked(isBackgroundBlurEnabled()); mBlurRadiusPreference.setValue(getSeekBarValue(mBlurRadiusKey, 60)); } private boolean isCustomEnabled() { return hasKey(mCustomBackgroundEnabledKey) && PrefsUtils.getSharedBoolPrefs(getContext(), mCustomBackgroundEnabledKey, false); } private void setColor() { mColorPickerPreference.setColor(getColor(2113929215)); } private int getColor(int defValue) { return hasKey(mColorKey) ? PrefsUtils.getSharedIntPrefs(getContext(), mColorKey, defValue) : defValue; } private boolean isBackgroundBlurEnabled() { return hasKey(mBlurEnabledKey) && PrefsUtils.getSharedBoolPrefs(getContext(), mBlurEnabledKey, false); } private int getSeekBarValue(String key, int defValue) { return hasKey(key) ? PrefsUtils.getSharedIntPrefs(getContext(), key, defValue) : defValue; } @Override public boolean onPreferenceChange(Preference preference, Object o) { if (preference == mCustomEnabledPreference) { setCustomEnable((Boolean) o); } else if (preference == mColorPickerPreference) { setBackgroundColor((int) o); } else if (preference == mCornerRadiusPreference) { setBackgroundCornerRadius((int) o); } else if (preference == mBlurEnabledPreference) { setBlurEnabled((Boolean) o); } else if (preference == mBlurRadiusPreference) { setBackgroundBlurRadius((int) o); } return false; } private void setCustomEnable(boolean isCustomEnabled) { mCustomEnabledPreference.setChecked(isCustomEnabled); PrefsUtils.mSharedPreferences.edit().putBoolean(mCustomBackgroundEnabledKey, isCustomEnabled).apply(); } private void setBackgroundColor(int value) { mColorPickerPreference.setColor(value); PrefsUtils.mSharedPreferences.edit().putInt(mColorKey, value).apply(); } private void setBackgroundCornerRadius(int value) { mCornerRadiusPreference.setValue(value); PrefsUtils.mSharedPreferences.edit().putInt(mCornerRadiusKey, value).apply(); } private void setBlurEnabled(boolean isBlurEnabled) { mBlurEnabledPreference.setChecked(isBlurEnabled); PrefsUtils.mSharedPreferences.edit().putBoolean(mBlurEnabledKey, isBlurEnabled).apply(); } private void setBackgroundBlurRadius(int value) { mBlurRadiusPreference.setValue(value); PrefsUtils.mSharedPreferences.edit().putInt(mBlurRadiusKey, value).apply(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/sub/MultiActionSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.sub; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.Bundle; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.SubPickerActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.Preference; import moralnorm.preference.RadioButtonPreference; public class MultiActionSettings extends SettingsPreferenceFragment { Bundle args; String mKey = null; String mActionKey; String mAppValue; RadioButtonPreference mClearMemory; RadioButtonPreference mInvertColors; RadioButtonPreference mNoAction; RadioButtonPreference mOpenNotificationCenter; RadioButtonPreference mScreenLock; RadioButtonPreference mScreenSleep; RadioButtonPreference mScreenCapture; RadioButtonPreference mOpenPowerMenu; RadioButtonPreference mScreenRecents; RadioButtonPreference mVolumeDialog; RadioButtonPreference mOpenApp; Preference mAppSelector; @Override public int getContentResId() { return R.xml.home_multi_action; } @Override public void initPrefs() { args = getArguments(); mKey = args.getString("key"); mActionKey = mKey + "_action"; mNoAction = findPreference("prefs_key_no_action"); mOpenNotificationCenter = findPreference("prefs_key_open_notification_center"); mScreenLock = findPreference("prefs_key_screen_lock"); mScreenSleep = findPreference("prefs_key_screen_sleep"); mScreenCapture = findPreference("prefs_key_screen_capture"); mOpenPowerMenu = findPreference("prefs_key_open_powermenu"); mClearMemory = findPreference("prefs_key_clear_memory"); mInvertColors = findPreference("prefs_key_invert_colors"); mScreenRecents = findPreference("prefs_key_screen_recents"); mVolumeDialog = findPreference("prefs_key_volume_dialog"); mOpenApp = findPreference("prefs_key_open_app"); mAppSelector = findPreference("prefs_key_open_app_selector"); updateAction(); } private void updateAction() { int value = hasKey(mActionKey) ? PrefsUtils.getSharedIntPrefs(getContext(), mActionKey, 0) : 0; switch (value) { case 0 -> mNoAction.setChecked(true); case 1 -> mOpenNotificationCenter.setChecked(true); case 2 -> mClearMemory.setChecked(true); case 3 -> mInvertColors.setChecked(true); case 4 -> mScreenLock.setChecked(true); case 5 -> mScreenSleep.setChecked(true); case 6 -> mScreenCapture.setChecked(true); case 7 -> mScreenRecents.setChecked(true); case 8 -> mVolumeDialog.setChecked(true); case 12 -> mOpenPowerMenu.setChecked(true); case 13 -> { mOpenApp.setChecked(true); updateAppSelectorTitle(); } } } @Override public boolean onPreferenceTreeClick(Preference preference) { if (preference != mAppSelector) { editActionIntSharedPrefs(getAction(preference)); } else { Intent intent = new Intent(getActivity(), SubPickerActivity.class); intent.putExtra("is_app_selector", true); startActivityForResult(intent, 0); } return true; } private int getAction(Preference preference) { if (preference == mOpenNotificationCenter) { return 1; } else if (preference == mClearMemory) { return 2; } else if (preference == mInvertColors) { return 3; } else if (preference == mScreenLock) { return 4; } else if (preference == mScreenSleep) { return 5; } else if (preference == mScreenCapture) { return 6; } else if (preference == mScreenRecents) { return 7; } else if (preference == mVolumeDialog) { return 8; } else if (preference == mOpenPowerMenu) { return 12; } else if (preference == mOpenApp) { return 13; } else { return 0; } } private void editActionIntSharedPrefs(int value) { PrefsUtils.mSharedPreferences.edit().putInt(mActionKey, value).apply(); } public void updateAppSelectorTitle() { if (hasKey(mKey + "_app")) { String title = getAppName(getContext(), PrefsUtils.mSharedPreferences.getString(mKey + "_app", "")); mAppSelector.setTitle(title); } } public static String getAppName(Context context, String pkgActName) { return getAppName(context, pkgActName, false); } public static String getAppName(Context context, String pkgActName, boolean forcePkg) { PackageManager pm = context.getPackageManager(); String notSelected = "None"; String[] pkgActArray = pkgActName.split("\\|"); ApplicationInfo ai; if (!pkgActName.equals(notSelected)) { if (pkgActArray.length >= 1 && pkgActArray[0] != null) try { if (!forcePkg && pkgActArray.length >= 2 && pkgActArray[1] != null && !"".equals(pkgActArray[1].trim())) { return pm.getActivityInfo(new ComponentName(pkgActArray[0], pkgActArray[1]), 0).loadLabel(pm).toString(); } else if (!"".equals(pkgActArray[0].trim())) { ai = pm.getApplicationInfo(pkgActArray[0], 0); return pm.getApplicationLabel(ai).toString(); } } catch (Throwable e) { e.printStackTrace(); } } return null; } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == 1) { String mAppPackageName = data.getStringExtra("appPackageName"); String mAppActivityName = data.getStringExtra("appActivityName"); PrefsUtils.mSharedPreferences.edit().putString(mKey + "_app", mAppPackageName + "|" + mAppActivityName).apply(); updateAppSelectorTitle(); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/ControlCenterSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidS; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidSv2; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.provider.Settings; import android.view.View; import android.widget.SeekBar; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.log.AndroidLogUtils; import miui.telephony.TelephonyManager; import moralnorm.preference.DropDownPreference; import moralnorm.preference.SeekBarPreferenceEx; import moralnorm.preference.SwitchPreference; public class ControlCenterSettings extends SettingsPreferenceFragment { SwitchPreference mFixMediaPanel; SwitchPreference mNotice; SwitchPreference mNoticex; SeekBarPreferenceEx mNewCCGrid; SwitchPreference mNewCCGridRect; SwitchPreference mFiveG; DropDownPreference mBluetoothSytle; // 临时的,旧控制中心 SwitchPreference mOldCCGrid; SwitchPreference mOldCCGrid1; @Override public int getContentResId() { return R.xml.system_ui_control_center; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity) getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } @Override public void initPrefs() { mFixMediaPanel = findPreference("prefs_key_system_ui_control_center_fix_media_control_panel"); mNewCCGrid = findPreference("prefs_key_system_control_center_cc_rows"); mNewCCGridRect = findPreference("prefs_key_system_ui_control_center_rounded_rect"); mNotice = findPreference("prefs_key_n_enable"); mNoticex = findPreference("prefs_key_n_enable_fix"); mBluetoothSytle = findPreference("prefs_key_system_ui_control_center_cc_bluetooth_tile_style"); mFiveG = findPreference("prefs_key_system_control_center_5g_tile"); mFixMediaPanel.setVisible(isAndroidS() || isAndroidSv2()); mNewCCGrid.setVisible(!isAndroidR()); mNewCCGridRect.setVisible(!isAndroidR()); mNotice.setVisible(!isAndroidR()); mNoticex.setVisible(isMoreAndroidVersion(33)); mBluetoothSytle.setVisible(!isAndroidR()); mFiveG.setVisible(TelephonyManager.getDefault().isFiveGCapable()); mOldCCGrid = findPreference("prefs_key_system_control_center_old_enable"); mOldCCGrid1 = findPreference("prefs_key_system_control_center_old_enable_1"); mOldCCGrid.setVisible(isMoreAndroidVersion(33)); mOldCCGrid1.setVisible(!isMoreAndroidVersion(33)); ((SeekBarPreferenceEx) findPreference("prefs_key_system_control_center_old_qs_grid_columns")).setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (!fromUser) return; if (progress < 3) progress = 5; try { Settings.Secure.putInt(requireActivity().getContentResolver(), "sysui_qqs_count", progress); } catch (Throwable t) { AndroidLogUtils.LogD("SeekBarPreferenceEx", "onProgressChanged -> system_control_center_old_qs_grid_columns", t); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/LockScreenSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui; import static com.sevtinge.cemiuiler.utils.api.LinQiqiApisKt.isDeviceEncrypted; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isMoreAndroidVersion; import android.os.Build; import android.view.View; import com.sevtinge.cemiuiler.R; import moralnorm.preference.SeekBarPreferenceEx; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.SwitchPreference; public class LockScreenSettings extends SettingsPreferenceFragment { SwitchPreference mBlurButton; // 锁屏按钮背景模糊 SwitchPreference mForceSystemFonts; // 时钟使用系统字体 SwitchPreference mPasswordFree; // 开机免输入密码 SeekBarPreferenceEx mChangingCVTime; // 充电信息显示刷新间隔 @Override public int getContentResId() { return R.xml.system_ui_lock_screen; } @Override public void initPrefs() { mBlurButton = findPreference("prefs_key_system_ui_lock_screen_blur_button"); mForceSystemFonts = findPreference("prefs_key_system_ui_lock_screen_force_system_fonts"); mPasswordFree = findPreference("prefs_key_system_ui_lock_screen_password_free"); mChangingCVTime = findPreference("prefs_key_system_ui_lock_screen_show_spacing"); mBlurButton.setVisible(!isAndroidR()); mForceSystemFonts.setVisible(!isAndroidR()); mChangingCVTime.setVisible(isMoreAndroidVersion(Build.VERSION_CODES.TIRAMISU)); if (isDeviceEncrypted(getContext())) { mPasswordFree.setChecked(false); mPasswordFree.setEnabled(false); mPasswordFree.setSummary(R.string.system_ui_lock_screen_password_free_tip); } } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/NavigationSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class NavigationSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.system_ui_navigation; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/StatusBarSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.Preference; public class StatusBarSettings extends SettingsPreferenceFragment { Preference mDeviceStatus; // 硬件指示器 @Override public int getContentResId() { return R.xml.system_ui_status_bar; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } @Override public void initPrefs() { mDeviceStatus = findPreference("prefs_key_system_ui_status_bar_device"); mDeviceStatus.setVisible(!isAndroidR()); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/SystemUIOtherSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.PreferenceCategory; public class SystemUIOtherSettings extends SettingsPreferenceFragment { PreferenceCategory mMonetOverlay; @Override public int getContentResId() { return R.xml.system_ui_other; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } @Override public void initPrefs() { mMonetOverlay = findPreference("prefs_key_system_ui_monet"); mMonetOverlay.setVisible(!isAndroidR()); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/statusbar/BatteryDetailIndicatorSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class BatteryDetailIndicatorSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.system_ui_status_bar_hardware_detail_indicator; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/statusbar/BatteryIndicatorSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar; import android.content.Intent; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.ColorPickerPreference; import moralnorm.preference.DropDownPreference; import moralnorm.preference.Preference; public class BatteryIndicatorSettings extends SettingsPreferenceFragment { DropDownPreference mBatteryIndicatorColor; ColorPickerPreference mBatteryIndicatorFullPower; ColorPickerPreference mBatteryIndicatorLowPower; ColorPickerPreference mBatteryIndicatorPowerSaving; ColorPickerPreference mBatteryIndicatorPowerCharging; Preference mBatteryIndicatorTest; @Override public int getContentResId() { return R.xml.system_ui_status_bar_battery_indicator; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } @Override public void initPrefs() { mBatteryIndicatorColor = findPreference("prefs_key_system_ui_status_bar_battery_indicator_color"); mBatteryIndicatorFullPower = findPreference("prefs_key_system_ui_status_bar_battery_indicator_color_full_power"); mBatteryIndicatorLowPower = findPreference("prefs_key_system_ui_status_bar_battery_indicator_color_low_power"); mBatteryIndicatorPowerSaving = findPreference("prefs_key_system_ui_status_bar_battery_indicator_color_power_saving"); mBatteryIndicatorPowerCharging = findPreference("prefs_key_system_ui_status_bar_battery_indicator_color_power_charging"); showBatteryIndicatorColor(Integer.parseInt(PrefsUtils.getSharedStringPrefs(getActivity(), mBatteryIndicatorColor.getKey(), "0"))); mBatteryIndicatorColor.setOnPreferenceChangeListener((preference, o) -> { showBatteryIndicatorColor(Integer.parseInt((String) o)); return true; }); mBatteryIndicatorTest = findPreference("prefs_key_system_ui_status_bar_battery_indicator_test"); mBatteryIndicatorTest.setOnPreferenceClickListener(preference -> { requireActivity().sendBroadcast(new Intent("moralnorm.module.BatteryIndicatorTest")); return true; }); } private void showBatteryIndicatorColor(int vale) { boolean showBatteryIndicatorColor = vale != 2; mBatteryIndicatorFullPower.setVisible(showBatteryIndicatorColor); mBatteryIndicatorLowPower.setVisible(showBatteryIndicatorColor); mBatteryIndicatorPowerSaving.setVisible(showBatteryIndicatorColor); mBatteryIndicatorPowerCharging.setVisible(showBatteryIndicatorColor); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/statusbar/BatteryStyleSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class BatteryStyleSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.system_ui_status_bar_battery_styles; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/statusbar/ClockIndicatorSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.DropDownPreference; import moralnorm.preference.Preference; import moralnorm.preference.PreferenceCategory; public class ClockIndicatorSettings extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener { DropDownPreference mClockModePreference; PreferenceCategory mDefault; PreferenceCategory mGeek; @Override public int getContentResId() { return R.xml.system_ui_status_bar_clock_indicator; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } @Override public void initPrefs() { int mClockMode = Integer.parseInt(PrefsUtils.getSharedStringPrefs(getContext(), "prefs_key_system_ui_statusbar_clock_mode", "0")); mClockModePreference = findPreference("prefs_key_system_ui_statusbar_clock_mode"); mDefault = findPreference("prefs_key_system_ui_statusbar_clock_default"); mGeek = findPreference("prefs_key_system_ui_statusbar_clock_geek"); setClockMode(mClockMode); mClockModePreference.setOnPreferenceChangeListener(this); } @Override public boolean onPreferenceChange(Preference preference, Object o) { if (preference == mClockModePreference) { setClockMode(Integer.parseInt((String) o)); } return true; } private void setClockMode(int mode) { mDefault.setVisible(mode == 1); mGeek.setVisible(mode == 2); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/statusbar/DoubleLineNetworkSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class DoubleLineNetworkSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.system_ui_status_bar_doubleline_network; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/statusbar/IconManageSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidT; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.DropDownPreference; import moralnorm.preference.Preference; import moralnorm.preference.SeekBarPreferenceEx; import moralnorm.preference.SwitchPreference; public class IconManageSettings extends SettingsPreferenceFragment { Preference UseNewHD; DropDownPreference IconNewHD; DropDownPreference mAlarmClockIcon; SeekBarPreferenceEx mAlarmClockIconN; SeekBarPreferenceEx mNotificationIconMaximum; SwitchPreference mBatteryNumber; SwitchPreference mBatteryPercentage; @Override public int getContentResId() { return R.xml.system_ui_status_bar_icon_manage; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } @Override public void initPrefs() { mAlarmClockIcon = findPreference("prefs_key_system_ui_status_bar_icon_alarm_clock"); mAlarmClockIconN = findPreference("prefs_key_system_ui_status_bar_icon_alarm_clock_n"); mNotificationIconMaximum = findPreference("prefs_key_system_ui_status_bar_notification_icon_maximum"); mBatteryNumber = findPreference("prefs_key_system_ui_status_bar_battery_percent"); mBatteryPercentage = findPreference("prefs_key_system_ui_status_bar_battery_percent_mark"); UseNewHD = findPreference("prefs_key_system_ui_status_bar_use_new_hd"); IconNewHD = findPreference("prefs_key_system_ui_status_bar_icon_new_hd"); UseNewHD.setVisible(isAndroidT()); IconNewHD.setVisible(isAndroidT()); mAlarmClockIconN.setVisible(Integer.parseInt(PrefsUtils.mSharedPreferences.getString("prefs_key_system_ui_status_bar_icon_alarm_clock", "0")) == 3); mAlarmClockIcon.setOnPreferenceChangeListener((preference, o) -> { mAlarmClockIconN.setVisible(Integer.parseInt((String) o) == 3); return true; }); mNotificationIconMaximum.setOnPreferenceChangeListener((preference, o) -> { if ((int) o == 16) { mNotificationIconMaximum.setValue(R.string.unlimited); } return true; }); mBatteryNumber.setOnPreferenceChangeListener((preference, o) -> { if (!(boolean) o) { mBatteryPercentage.setChecked(false); } return true; }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/statusbar/MobileNetworkTypeSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MobileNetworkTypeSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.system_ui_status_bar_mobile_network_type; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/systemui/statusbar/NetworkSpeedIndicatorSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar; import static com.sevtinge.cemiuiler.utils.devicesdk.SystemSDKKt.isAndroidR; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import moralnorm.preference.SeekBarPreferenceEx; public class NetworkSpeedIndicatorSettings extends SettingsPreferenceFragment { SeekBarPreferenceEx mNetworkSpeedWidth; // 固定宽度 @Override public int getContentResId() { return R.xml.system_ui_status_bar_network_speed_indicator; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartDialog( getResources().getString(R.string.system_ui), "com.android.systemui" ); } @Override public void initPrefs() { mNetworkSpeedWidth = findPreference("prefs_key_system_ui_statusbar_network_speed_fixedcontent_width"); mNetworkSpeedWidth.setVisible(!isAndroidR()); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/various/AOSPSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.various; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class AOSPSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.various_aosp; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/various/AlertDialogSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.various; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.DropDownPreference; import moralnorm.preference.SeekBarPreferenceEx; public class AlertDialogSettings extends SettingsPreferenceFragment { private DropDownPreference mDialogGravity; private SeekBarPreferenceEx mDialogHorizontalMargin; private SeekBarPreferenceEx mDialogBottomMargin; @Override public int getContentResId() { return R.xml.various_dialog; } @Override public void initPrefs() { mDialogGravity = findPreference("prefs_key_various_dialog_gravity"); mDialogHorizontalMargin = findPreference("prefs_key_various_dialog_margin_horizontal"); mDialogBottomMargin = findPreference("prefs_key_various_dialog_margin_bottom"); int gialogGravity = Integer.parseInt(PrefsUtils.getSharedStringPrefs(getActivity(), "prefs_key_various_dialog_gravity", "0")); mDialogHorizontalMargin.setVisible(gialogGravity != 0); mDialogBottomMargin.setVisible(gialogGravity == 2); mDialogGravity.setOnPreferenceChangeListener((preference, o) -> { int i = Integer.parseInt((String) o); mDialogHorizontalMargin.setVisible(i != 0); mDialogBottomMargin.setVisible(i == 2); return true; }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/fragment/various/MiPadSettings.java ================================================ package com.sevtinge.cemiuiler.ui.fragment.various; import android.view.View; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.BaseSettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class MiPadSettings extends SettingsPreferenceFragment { @Override public int getContentResId() { return R.xml.various_mipad; } @Override public View.OnClickListener addRestartListener() { return view -> ((BaseSettingsActivity)getActivity()).showRestartSystemDialog(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/various/LocationDataActivity.java ================================================ package com.sevtinge.cemiuiler.ui.various; import android.annotation.SuppressLint; import android.content.Context; import android.database.Cursor; import android.os.Bundle; import android.text.TextUtils; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.data.LocationData; import com.sevtinge.cemiuiler.data.SQLiteHelper; import com.sevtinge.cemiuiler.utils.ToastHelper; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import moralnorm.appcompat.app.AlertDialog; import moralnorm.appcompat.app.AppCompatActivity; public class LocationDataActivity extends AppCompatActivity implements View.OnClickListener { private Cursor mCursor; private ListView mLocationListView; private LocationAdapter mAdapter; private SQLiteHelper mSQLiteHelper; private ArrayList mLocationDataList = new ArrayList<>(); Button mAddLocation; EditText mTitle; EditText mOffset; EditText mBaseStation; EditText mLongitudeAndLatitude; EditText mRemarks; @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(R.layout.activity_location); mAddLocation = findViewById(R.id.location_add); mAddLocation.setOnClickListener(this); mSQLiteHelper = new SQLiteHelper(this); mAdapter = new LocationAdapter(this, mLocationDataList); mLocationListView = findViewById(R.id.list_location); mLocationListView.setAdapter(mAdapter); mCursor = mSQLiteHelper.a.rawQuery("select * from location order by id desc limit 2000", null); if (mCursor.moveToFirst()) { do { LocationData locationData = new LocationData(String.valueOf(mCursor.getString(0)), mCursor.getDouble(1), mCursor.getDouble(2), mCursor.getInt(3), mCursor.getInt(4), mCursor.getInt(5), mCursor.getString(6), mCursor.getInt(7)); mLocationDataList.add(locationData); } while (mCursor.moveToNext()); } mCursor.close(); registerForContextMenu(mLocationListView); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { if (v.getId() == R.id.list_location) { menu.setHeaderTitle(String.valueOf(mLocationDataList.get(((AdapterView.AdapterContextMenuInfo) menuInfo).position).getRemarks())); getMenuInflater().inflate(R.menu.menu_location, menu); } else { super.onCreateContextMenu(menu, v, menuInfo); } } @Override public void onClick(View v) { if (v == mAddLocation) { View view = LayoutInflater.from(this).inflate(R.layout.location_edit_dialog, null); initEditView(view); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("新增"); builder.setView(view); builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { String title = mTitle.getText().toString(); String offset = mOffset.getText().toString(); String baseStation = mBaseStation.getText().toString(); String longitudeAndLatitude = mLongitudeAndLatitude.getText().toString(); String remarks = mRemarks.getText().toString(); if (TextUtils.isEmpty(title) || TextUtils.isEmpty(offset) || TextUtils.isEmpty(baseStation) || TextUtils.isEmpty(longitudeAndLatitude) || TextUtils.isEmpty(remarks)) { ToastHelper.makeText(this, "格式错误"); } else { String[] split = baseStation.split(",", 2); String[] split2 = longitudeAndLatitude.split(",", 2); LocationData mData = new LocationData(title, Double.parseDouble(split2[0]), Double.parseDouble(split2[1]), Integer.parseInt(offset), Integer.parseInt(split[0]), Integer.parseInt(split[1]), remarks, 1); /*mData.setTitle(title); mData.setLongitude(Double.parseDouble(split2[0])); mData.setLatitude(Double.parseDouble(split2[1])); mData.setOffset(Integer.parseInt(offset)); mData.setRegionCode(Integer.parseInt(split[0])); mData.setBaseStationCode(Integer.parseInt(split[1])); mData.setRemarks(remarks); mData.setF(1);*/ long b2 = mSQLiteHelper.b(mData); if (b2 < 0) { ToastHelper.makeText(this, "Can't insert"); return; } mData.setF((int) b2); mLocationDataList.add(0, mData); mAdapter.notifyDataSetChanged(); } }); builder.setNegativeButton(android.R.string.cancel, null).show(); } } @SuppressLint("NonConstantResourceId") @Override public boolean onContextItemSelected(@NonNull MenuItem item) { final AdapterView.AdapterContextMenuInfo mMenuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); final LocationData mDataPosition = mLocationDataList.get(mMenuInfo.position); if (item.getItemId() == R.id.location_add) { final EditText editText = new EditText(this); View view = LayoutInflater.from(this).inflate(R.layout.location_edit_dialog, null); initEditView(view); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("新增"); builder.setView(view); builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { String n = n(editText.getText().toString()); if ("".equals(n) || !e(n)) { ToastHelper.makeText(this, "格式错误"); return; } String[] split = n.split(",", 6); LocationData kVar2 = new LocationData(String.valueOf(split[0]), Double.parseDouble(split[1]), Double.parseDouble(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4]), Integer.parseInt(split[5]), split[6], 7); long b2 = mSQLiteHelper.b(kVar2); if (b2 < 0) { ToastHelper.makeText(this, "Can't insert"); return; } kVar2.setF((int) b2); mLocationDataList.add(0, kVar2); mAdapter.notifyDataSetChanged(); }); builder.setNegativeButton(android.R.string.cancel, null).show(); } else if (item.getItemId() == R.id.location_delete) { mLocationDataList.remove(mMenuInfo.position); mAdapter.notifyDataSetChanged(); if (mSQLiteHelper.a(mDataPosition) != 1) { ToastHelper.makeText(this, "Can't delete."); } } else { return super.onContextItemSelected(item); } return true; } private void initEditView(View view) { mTitle = view.findViewById(R.id.title); mOffset = view.findViewById(R.id.offset); mBaseStation = view.findViewById(R.id.base_station); mLongitudeAndLatitude = view.findViewById(R.id.longitude_latitude); mRemarks = view.findViewById(R.id.remarks); } public static String n(String str) { return str.replaceAll("\\s+", ""); } public static boolean e(String str) { return Pattern.compile("^((-?\\d+(\\.\\d+)?,){2}(\\d+,){3}.+)$").matcher(str).matches(); } public class LocationAdapter extends ArrayAdapter { private List mList; private LayoutInflater mInflater; public LocationAdapter(@NonNull Context context, List list) { super(context, (int) R.layout.item_location, list); mList = list; mInflater = getLayoutInflater(); } @Override public int getCount() { return mList.size(); } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { LocationData mData = getItem(position); ViewHolder holder; if (convertView == null) { convertView = mInflater.inflate(R.layout.item_location, parent, false); holder = new ViewHolder(); holder.mTitle = convertView.findViewById(android.R.id.title); holder.mRegionCode = convertView.findViewById(R.id.region_code); holder.mBaseStation = convertView.findViewById(R.id.base_station); holder.mLongitudeAndLatitude = convertView.findViewById(R.id.longitude_latitude); holder.mSummary = convertView.findViewById(android.R.id.summary); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.mTitle.setText(mData.getTitle()); holder.mRegionCode.setText("偏移:" + mData.getOffset()); holder.mBaseStation.setText("基站:" + mData.getRegionCode() + "," + mData.getBaseStationCode()); holder.mLongitudeAndLatitude.setText("经纬度:" + mData.getLongitude() + "," + mData.getLatitude()); holder.mSummary.setText(mData.toString()); holder.mSummary.setVisibility(View.VISIBLE); return convertView; } class ViewHolder { TextView mTitle; TextView mRegionCode; TextView mBaseStation; TextView mLongitudeAndLatitude; TextView mSummary; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/various/LocationSimulationActivity.java ================================================ package com.sevtinge.cemiuiler.ui.various; import android.content.SharedPreferences; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.ui.base.SettingsActivity; import com.sevtinge.cemiuiler.ui.fragment.base.SettingsPreferenceFragment; public class LocationSimulationActivity extends SettingsActivity { private static SharedPreferences mSharedPrefs; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setImmersionMenuEnabled(true); setFragment(new LocationSimulationFragment()); } public static class LocationSimulationFragment extends SettingsPreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSharedPrefs = getPreferenceManager().getSharedPreferences(); setSharedPreferenceChanged(); } @Override public int getContentResId() { return R.xml.various_location_simulation; } @Override public void initPrefs() { super.initPrefs(); } @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { setSharedPreferenceChanged(); } private void setSharedPreferenceChanged() { } @Override public void onResume() { super.onResume(); mSharedPrefs.registerOnSharedPreferenceChangeListener(this); } @Override public void onPause() { super.onPause(); mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_location_simulation, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { if (item.getItemId() == R.id.location_simulation_data) { } return super.onOptionsItemSelected(item); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/ui/various/fragment/VariousFragment.java ================================================ package com.sevtinge.cemiuiler.ui.various.fragment; import android.os.Bundle; import android.util.Log; import com.sevtinge.cemiuiler.utils.PrefsUtils; import moralnorm.preference.DropDownPreference; import moralnorm.preference.PreferenceCategory; import moralnorm.preference.PreferenceFragmentCompat; import moralnorm.preference.SeekBarPreference; import moralnorm.preference.SwitchPreference; public class VariousFragment extends PreferenceFragmentCompat { public String TAG = "VariousFragment"; private SeekBarPreference mDialogHorizontalMargin; private SeekBarPreference mDialogBottomMargin; private PreferenceCategory mBlurEnabledCat; private PreferenceCategory mBlurCustomCat; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Bundle args = getArguments(); assert args != null; String sub = args.getString("sub"); if (sub == null) return; Log.d(TAG, "MoralNorm: " + getArguments()); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void onCreatePreferences(Bundle bundle, String s) { DropDownPreference mDialogGravity = findPreference("prefs_key_various_dialog_gravity"); mDialogHorizontalMargin = findPreference("prefs_key_various_dialog_horizontal_margin"); mDialogBottomMargin = findPreference("prefs_key_various_dialog_bottom_margin"); SwitchPreference mBlurEnabled = findPreference("prefs_key_various_blur_enabled"); mBlurEnabledCat = findPreference("prefs_key_various_blur_enabled_cat"); mBlurCustomCat = findPreference("prefs_key_various_blur_custom"); int gialogGravity = Integer.parseInt(PrefsUtils.getSharedStringPrefs(getActivity(), "prefs_key_various_dialog_gravity", "0")); mDialogHorizontalMargin.setVisible(gialogGravity != 0); mDialogBottomMargin.setVisible(gialogGravity == 2); mDialogGravity.setOnPreferenceChangeListener((preference, o) -> { int i = Integer.parseInt((String) o); mDialogHorizontalMargin.setVisible(i != 0); mDialogBottomMargin.setVisible(i == 2); return true; }); boolean bluEnabled = PrefsUtils.getSharedBoolPrefs(getActivity(), "prefs_key_various_blur_enabled", false); mBlurEnabledCat.setVisible(bluEnabled); mBlurCustomCat.setVisible(bluEnabled); mBlurEnabled.setOnPreferenceChangeListener((preference, o) -> { mBlurEnabledCat.setVisible((Boolean) o); mBlurCustomCat.setVisible((Boolean) o); return true; }); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/BackupUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import com.sevtinge.hyperceiler.expansionpacks.utils.KS2Utils; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import androidx.annotation.Nullable; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; import java.util.Iterator; import java.util.Map; public class BackupUtils { public static final int CREATE_DOCUMENT_CODE = 255774; public static final int OPEN_DOCUMENT_CODE = 277451; public static final String BACKUP_FILE_NAME = "Cemiuiler_settings_backup"; public static void backup(Activity activity) { @SuppressLint("SimpleDateFormat") String backupFileName = BACKUP_FILE_NAME + new SimpleDateFormat("_yyyy-MM-dd-HH:mm:ss").format(new java.util.Date()); Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("application/json"); intent.putExtra(Intent.EXTRA_TITLE, backupFileName); activity.startActivityForResult(intent, CREATE_DOCUMENT_CODE); } public static void restore(Activity activity) { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("application/json"); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false); activity.startActivityForResult(intent, OPEN_DOCUMENT_CODE); } public static void handleCreateDocument(Activity activity, @Nullable Uri data) throws IOException, JSONException { if (data == null) return; OutputStream outputStream = activity.getContentResolver().openOutputStream(data); BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream)); JSONObject jsonObject = new JSONObject(); for (Map.Entry entry : PrefsUtils.mSharedPreferences.getAll().entrySet()) { jsonObject.put(entry.getKey(), entry.getValue()); } bufferedWriter.write(jsonObject.toString()); bufferedWriter.close(); } public static void handleReadDocument(Activity activity, @Nullable Uri data) throws IOException, JSONException { if (data == null) return; SharedPreferences.Editor edit = PrefsUtils.mSharedPreferences.edit(); InputStream inputStream = activity.getContentResolver().openInputStream(data); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder stringBuilder = new StringBuilder(); String line = bufferedReader.readLine(); while (line != null) { stringBuilder.append(line); line = bufferedReader.readLine(); } String read = stringBuilder.toString(); JSONObject jsonObject = new JSONObject(read); Iterator keys = jsonObject.keys(); while (keys.hasNext()) { String key = keys.next(); Object value = jsonObject.get(key); if (value instanceof String) { edit.putString(key, (String) value); } else if (value instanceof Boolean) { edit.putBoolean(key, (Boolean) value); } else if (value instanceof Integer) { edit.putInt(key, (Integer) value); } } edit.apply(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/BitmapUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.PixelFormat; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; import java.io.ByteArrayOutputStream; public class BitmapUtils { public static Bitmap drawableToBitmap(Drawable drawable) { // 取 drawable 的长宽 int w = drawable.getIntrinsicWidth(); int h = drawable.getIntrinsicHeight(); // 取 drawable 的颜色格式 Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; // 建立对应 bitmap Bitmap bitmap = Bitmap.createBitmap(w, h, config); // 建立对应 bitmap 的画布 Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, w, h); // 把 drawable 内容画到画布中 drawable.draw(canvas); return bitmap; } Bitmap drawable2Bitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } else if (drawable instanceof NinePatchDrawable) { Bitmap bitmap = Bitmap .createBitmap( drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); drawable.draw(canvas); return bitmap; } else { return null; } } public static byte[] Bitmap2Bytes(Bitmap bm) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.PNG, 100, baos); return baos.toByteArray(); } public static Bitmap Bytes2Bimap(byte[] b) { if (b.length != 0) { return BitmapFactory.decodeByteArray(b, 0, b.length); } else { return null; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/BlurUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.text.TextUtils; import android.view.View; import androidx.annotation.RequiresApi; import com.sevtinge.cemiuiler.XposedInit; import de.robv.android.xposed.XposedHelpers; @RequiresApi(Build.VERSION_CODES.S) public class BlurUtils { private final Context mContext; private Object mViewRootImpl; private Drawable mBlurDrawable; private int mColor; private int mAlpha; private int mCornerRadius; private int mBlurRadius; private boolean isBlurEnable; public BlurUtils(View view) { this(view, ""); } public BlurUtils(View view, String key) { mContext = view.getContext(); setKey(mContext, key); setBlurView(view); } public void setBlurView(View view) { setOnAttachStateChangeListener(view); } public void setBlurEnable(boolean blurEnable) { isBlurEnable = blurEnable; } public void setKey(Context context, String key) { if (!TextUtils.isEmpty(key)) { String mBlurEnableKey = key + "_blur_enabled"; String mBlurRadiusKey = key + "_blur_radius"; String mColorKey = key + "_color"; String mAlphaKey = key + "_color_alpha"; String mCornerRadiusKey = key + "_corner_radius"; isBlurEnable = XposedInit.mPrefsMap.getBoolean(mBlurEnableKey); mBlurRadius = XposedInit.mPrefsMap.getInt(mBlurRadiusKey, 60); mColor = XposedInit.mPrefsMap.getInt(mColorKey, 2113929215); mAlpha = XposedInit.mPrefsMap.getInt(mAlphaKey, 60); mCornerRadius = DisplayUtils.dip2px(context, XposedInit.mPrefsMap.getInt(mCornerRadiusKey, 18)); } else { isBlurEnable = false; mBlurRadius = 60; mColor = 2113929215; mAlpha = 60; mCornerRadius = DisplayUtils.dip2px(context, 90); } } private void setOnAttachStateChangeListener(View view) { view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { mViewRootImpl = XposedHelpers.callMethod(v, "getViewRootImpl"); mBlurDrawable = createBackgroundDrawable(mViewRootImpl, isBlurEnable, ColorUtilsStatic.colorToHexARGB(mColor), mCornerRadius, mBlurRadius); v.setBackground(mBlurDrawable); } @Override public void onViewDetachedFromWindow(View v) { v.setBackground(null); } }); } private Drawable createBackgroundDrawable(Object viewRootImpl, boolean isBlurEnable, int color, int cornerRadius, int blurRadius) { Drawable mBackgroundDrawable; if (isBlurEnable) { mBackgroundDrawable = (Drawable) XposedHelpers.callMethod(viewRootImpl, "createBackgroundBlurDrawable", new Object[0]); setColor(mBackgroundDrawable, color); setCornerRadius(mBackgroundDrawable, cornerRadius); setBlurRadius(mBackgroundDrawable, blurRadius); } else { mBackgroundDrawable = createGradientDrawable(color, cornerRadius); } return mBackgroundDrawable; } private Drawable createBackgroundDrawable(Object viewRootImpl, boolean isBlurEnable, String color, int cornerRadius, int blurRadius) { Drawable mBackgroundDrawable; if (isBlurEnable) { mBackgroundDrawable = (Drawable) XposedHelpers.callMethod(viewRootImpl, "createBackgroundBlurDrawable", new Object[0]); setColor(mBackgroundDrawable, color); setCornerRadius(mBackgroundDrawable, cornerRadius); setBlurRadius(mBackgroundDrawable, blurRadius); } else { mBackgroundDrawable = createGradientDrawable(color, cornerRadius); } return mBackgroundDrawable; } private GradientDrawable createGradientDrawable(int color, int cornerRadius) { int mColorAlpha = (color & 0xff000000) >> 24; int mColorRed = (color & 0x00ff0000) >> 16; int mColorGreen = (color & 0x0000ff00) >> 8; int mColorBlue = (color & 0x000000ff); GradientDrawable mBackgroundDrawable = new GradientDrawable(); mBackgroundDrawable.setShape(GradientDrawable.RECTANGLE); mBackgroundDrawable.setColor(Color.argb(mColorAlpha, mColorRed, mColorGreen, mColorBlue)); mBackgroundDrawable.setCornerRadius(cornerRadius); return mBackgroundDrawable; } private GradientDrawable createGradientDrawable(String color, int cornerRadius) { GradientDrawable mBackgroundDrawable = new GradientDrawable(); mBackgroundDrawable.setShape(GradientDrawable.RECTANGLE); mBackgroundDrawable.setColor(Color.parseColor(color)); mBackgroundDrawable.setCornerRadius(cornerRadius); return mBackgroundDrawable; } public void setColor(Drawable drawable, int color) { int mColorAlpha = (color & 0xff000000) >> 24; int mColorRed = (color & 0x00ff0000) >> 16; int mColorGreen = (color & 0x0000ff00) >> 8; int mColorBlue = (color & 0x000000ff); XposedHelpers.callMethod(drawable, "setColor", Color.argb(mColorAlpha, mColorRed, mColorGreen, mColorBlue)); } public void setColor(Drawable drawable, String color) { XposedHelpers.callMethod(drawable, "setColor", Color.parseColor(color)); } public void setCornerRadius(Drawable drawable, int cornerRadius) { XposedHelpers.callMethod(drawable, "setCornerRadius", new Object[]{cornerRadius}); } public void setBlurRadius(Drawable drawable, int blurRadius) { XposedHelpers.callMethod(drawable, "setBlurRadius", new Object[]{blurRadius}); } /*public BlurUtils(View view) { this(view, null); } public BlurUtils(View view, String key) { mView = view; mKey = key; if (mView != null) { mContext = mView.getContext(); } if (mKey != null) { mBlurRadiusKey = mKey + "_blur_radius"; mBgCornerRadiusKey = mKey + "_bg_corner_radius"; mBgAlphaKey = mKey + "_bg_alpha"; mBgColorKey = mKey + "_bg_color"; mBlurRadius = XposedInit.mPrefsMap.getInt(mBlurRadiusKey,60); mBgCornerRadius = DisplayUtils.dip2px(mContext, XposedInit.mPrefsMap.getInt(mBgCornerRadiusKey, 90)); mBgAlpha = XposedInit.mPrefsMap.getInt(mBgAlphaKey,60); mBgColor = XposedInit.mPrefsMap.getInt(mBgColorKey,-1); } setBlur(mView); } void setBlur(View view) { view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { onAttachedToWindow(); } @Override public void onViewDetachedFromWindow(View v) { onDetachedFromWindow(); } }); } void onAttachedToWindow() { mViewRootImpl = XposedHelpers.callMethod(mView,"getViewRootImpl",new Object[0]); mBlurDrawable = (Drawable) XposedHelpers.callMethod(mViewRootImpl,"createBackgroundBlurDrawable",new Object[0]); initBlur(); } void onDetachedFromWindow() { mView.setBackground(null); } void initBlur() { setBlurRadius(); setCornerRadius(); setColor(); setBlurBackground(); } void setBlurBackground() { mView.setBackground(mBlurDrawable); } void setBlurRadius() { XposedHelpers.callMethod(mBlurDrawable,"setBlurRadius",new Object[]{mBlurRadius}); } void setCornerRadius() { XposedHelpers.callMethod(mBlurDrawable,"setCornerRadius",new Object[]{mBgCornerRadius}); } private static void setColor() { int mColorRed = (mBgColor & 0x00ff0000) >> 16; int mColorGreen = (mBgColor & 0x0000ff00) >> 8; int mColorBlue = (mBgColor & 0x000000ff); XposedHelpers.callMethod(mBlurDrawable,"setColor", Color.argb(mBgAlpha, mColorRed, mColorGreen, mColorBlue)); }*/ } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/ColorUtils.kt ================================================ package com.sevtinge.cemiuiler.utils import android.graphics.Color import com.sevtinge.cemiuiler.utils.log.XposedLogUtils object ColorUtils { // color转换不可靠,加一个默认值 private val defaultReturnColor = Color.argb(50, 0, 0, 0) fun colorToHex(color: Int): String { var originalColor = Color.valueOf(defaultReturnColor) try { originalColor = Color.valueOf(color) } catch (e: Throwable) { // 颜色转换失败 XposedLogUtils.logI("colorToHex", "ColorUtils colorToHex Hook failed by: $e") } val alpha = (originalColor.alpha() * 255).toInt() val red = (originalColor.red() * 255).toInt() val green = (originalColor.green() * 255).toInt() val blue = (originalColor.blue() * 255).toInt() val alphaHex = if (alpha <= 15) { "0$alpha" } else { alpha.toString(16) } val redHex = if (red <= 15) { "0$red" } else { red.toString(16) } val greenHex = if (green <= 15) { "0$green" } else { green.toString(16) } val blueHex = if (blue <= 15) { "0$blue" } else { blue.toString(16) } return "#$alphaHex$redHex$greenHex$blueHex".uppercase() } fun hexToColor(hexString: String): Int { return try { Color.parseColor(hexString) } catch (e: Throwable) { defaultReturnColor } } fun isDarkColor(color: Int): Boolean { val darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255 return darkness > 0.5 } fun addAlphaForColor(color: Int, alpha: Int): Int { return Color.valueOf(Color.red(color) / 255f, Color.green(color) / 255f, Color.blue(color) / 255f, alpha / 255f) .toArgb() } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/ColorUtilsStatic.java ================================================ package com.sevtinge.cemiuiler.utils; import android.graphics.Color; import androidx.annotation.ColorInt; public class ColorUtilsStatic { /** * @return 字符串 * @color: 参数 * 类型:int * 例如:-1272178 */ public static String colorToRGBA(int color) { int alpha = color >>> 24; int r = (color & 0xff0000) >> 16; int g = (color & 0xff00) >> 8; int b = color & 0xff; return alpha + ", " + r + ", " + g + ", " + b; } /** * @return 字符串 * @red 红色数值 * @green 绿色数值 * @blue 蓝色色数值 */ public static String rgbToHex(int red, int green, int blue) { String hr = Integer.toHexString(red); String hg = Integer.toHexString(green); String hb = Integer.toHexString(blue); return "#" + hr + hg + hb; } /** * 将 颜色值 转化为 #AARRGGBB * * @param color -1272178 * @return #AARRGGBB */ public static String colorToHexARGB(@ColorInt int color) { // 转化为16进制字符串 String A = Integer.toHexString(Color.alpha(color)); String R = Integer.toHexString(Color.red(color)); String G = Integer.toHexString(Color.green(color)); String B = Integer.toHexString(Color.blue(color)); // 判断获取到的R,G,B值的长度 如果长度等于1 给R,G,B值的前边添0 A = A.length() == 1 ? "0" + A : A; R = R.length() == 1 ? "0" + R : R; G = G.length() == 1 ? "0" + G : G; B = B.length() == 1 ? "0" + B : B; // StringBuilder sb = new StringBuilder(); sb.append("#"); sb.append(A); sb.append(R); sb.append(G); sb.append(B); return sb.toString(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/CtaUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import com.sevtinge.cemiuiler.R; public class CtaUtils { private static final String APP_PERMISSION_MANAGE_PKG = "com.miui.securitycenter"; public static final String ACTION_START_CTA_V2 = "miui.intent.action.SYSTEM_PERMISSION_DECLARE"; public static final String ACTION_START_CTA_V2_NEW = "miui.intent.action.SYSTEM_PERMISSION_DECLARE_NEW"; private static final String KEY_MANDATORY_PERMISSION = "mandatory_permission"; private static final String KEY_MAIN_PURPOSE = "main_purpose"; private static final String KEY_USE_NETWORK = "use_network"; private static final String KEY_OPTIONAL_PERM = "optional_perm"; private static final String KEY_OPTIONAL_PERM_DESC = "optional_perm_desc"; private static final String KEY_OPTIONAL_PERM_SHOW = "optional_perm_show"; private static final String KEY_SHOW_LOCK = "show_lock"; private static final String KEY_AGREE_DESC = "agree_desc"; public static void setCtaEnabled(Context context) { SharedPreferences.Editor edit = context.getSharedPreferences("Cemiuiler_Permission", 0).edit(); edit.putBoolean("key_new_cta_open", true); edit.apply(); } public static boolean isCtaEnabled(Context context) { return context.getSharedPreferences("Cemiuiler_Permission", 0).getBoolean("key_new_cta_open", false); } public static boolean showCtaDialog(Activity activity, int requestCode) { Intent intent = new Intent(); int mActivities = activity.getPackageManager().queryIntentActivities(intent, 0).size(); intent.setAction(mActivities > 0 ? ACTION_START_CTA_V2_NEW : ACTION_START_CTA_V2); intent.setPackage(APP_PERMISSION_MANAGE_PKG); intent.putExtra(KEY_MANDATORY_PERMISSION, true); intent.putExtra("all_purpose", activity.getString(R.string.new_cta_app_all_purpose_title)); intent.putExtra("runtime_perm", getRuntimePermission()); intent.putExtra("runtime_perm_desc", getRuntimePermissionDesc(activity)); intent.putExtra(KEY_OPTIONAL_PERM, getOptionalPermission()); intent.putExtra(KEY_OPTIONAL_PERM_DESC, getOptionalPermissionDesc(activity)); intent.putExtra(KEY_OPTIONAL_PERM_SHOW, false); intent.putExtra(KEY_AGREE_DESC, activity.getResources().getString(R.string.new_cta_agree_desc)); intent.putExtra("user_agreement", "https://cemiuiler.sevtinge.cc/Protocol"); intent.putExtra("privacy_policy", "https://cemiuiler.sevtinge.cc/Privacy"); intent.putExtra(KEY_USE_NETWORK, false); intent.putExtra(KEY_SHOW_LOCK, false); try { /*if (!supportNewPermissionStyle() || activity.getPackageManager().queryIntentActivities(intent, 0).size() <= 0) { return false; }*/ activity.startActivityForResult(intent, requestCode); return true; } catch (Exception unused) { return false; } } private static String[] getRuntimePermission() { return new String[0]; } private static String[] getRuntimePermissionDesc(Activity activity) { return new String[0]; } private static String[] getOptionalPermission() { return new String[0]; } private static String[] getOptionalPermissionDesc(Activity activity) { return new String[0]; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/DexKit.kt ================================================ package com.sevtinge.cemiuiler.utils import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam import org.luckypray.dexkit.DexKitBridge import org.luckypray.dexkit.query.enums.StringMatchType import org.luckypray.dexkit.query.matchers.ClassMatcher import org.luckypray.dexkit.query.matchers.MethodMatcher /** * DexKit 工具 */ object DexKit { private lateinit var hostDir: String private var isInitialized = false val dexKitBridge: DexKitBridge by lazy { System.loadLibrary("dexkit") DexKitBridge.create(hostDir)!!.also { isInitialized = true } } /** * 初始化 DexKit 的 apk 完整路径 */ fun initDexKit(loadPackageParam: LoadPackageParam) { hostDir = loadPackageParam.appInfo.sourceDir } /** * 关闭 DexKit bridge */ fun closeDexKit() { if (isInitialized) dexKitBridge.close() } /** * DexKit 封装查找方式 */ fun MethodMatcher.addUsingStringsEquals(vararg strings: String) { for (string in strings) { addUsingString(string, StringMatchType.Equals) } } fun ClassMatcher.addUsingStringsEquals(vararg strings: String) { for (string in strings) { addUsingString(string, StringMatchType.Equals) } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/DialogHelper.java ================================================ package com.sevtinge.cemiuiler.utils; import android.app.Activity; import android.content.DialogInterface; import moralnorm.appcompat.app.AlertDialog; public class DialogHelper { public static void showDialog(Activity activity, String title, String message) { showDialog(activity, title, message, null); } public static void showDialog(Activity activity, String title, String message, DialogInterface.OnClickListener onClickListener) { new AlertDialog.Builder(activity) .setTitle(title) .setMessage(message) .setPositiveButton(android.R.string.ok, onClickListener) .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss()) .show(); } public static void showDialog(Activity activity, int title, int message, DialogInterface.OnClickListener onClickListener) { new AlertDialog.Builder(activity) .setTitle(title) .setMessage(message) .setPositiveButton(android.R.string.ok, onClickListener) .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss()) .show(); } public static void showPositiveButtonDialog(Activity activity, String title, String message, DialogInterface.OnClickListener onClickListener) { new AlertDialog.Builder(activity) .setTitle(title) .setMessage(message) .setPositiveButton(android.R.string.ok, onClickListener) .show(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/DisplayUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import android.content.Context; import android.util.DisplayMetrics; import android.view.WindowManager; public class DisplayUtils { public static float mDensity; public static int mDensityDpi; public static DisplayMetrics mDisplayMetrics; public static int mHeightDps; public static int mHeightPixels; public static int mWidthDps; public static int mWidthPixels; public static void getAndroidScreenProperty(Context context) { mDisplayMetrics = new DisplayMetrics(); ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(mDisplayMetrics); mWidthPixels = mDisplayMetrics.widthPixels; mHeightPixels = mDisplayMetrics.heightPixels; mDensity = mDisplayMetrics.density; mDensityDpi = mDisplayMetrics.densityDpi; float f = mDensity; mWidthDps = (int) ((float) mWidthPixels / f); mHeightDps = (int) ((float) mHeightPixels / f); } public static int dip2px(Context context, float dipValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/Helpers.java ================================================ package com.sevtinge.cemiuiler.utils; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogI; import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityOptions; import android.app.Application; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.Shader; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.Handler; import android.util.LruCache; import android.widget.TextView; import com.sevtinge.cemiuiler.BuildConfig; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.provider.SharedPrefsProvider; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.io.File; import java.lang.reflect.Method; import java.util.LinkedHashSet; import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; import moralnorm.internal.utils.ReflectUtils; public class Helpers { private static final String TAG = "Helpers"; @SuppressLint("StaticFieldLeak") public static Context mModuleContext = null; public static boolean isModuleActive = false; public static int XposedVersion = 0; public static String mAppModulePkg = BuildConfig.APPLICATION_ID; public static final int REQUEST_PERMISSIONS_BACKUP = 1; public static final int REQUEST_PERMISSIONS_RESTORE = 2; public static LruCache memoryCache = new LruCache<>((int) (Runtime.getRuntime().maxMemory() / 1024) / 2) { @Override protected int sizeOf(String key, Bitmap icon) { if (icon != null) { return icon.getAllocationByteCount() / 1024; } else { return 130 * 130 * 4 / 1024; } } }; public static synchronized Context getProtectedContext(Context context) { return context.createDeviceProtectedStorageContext(); } public static boolean checkStorageReadable(Activity activity) { String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY) || state.equals(Environment.MEDIA_MOUNTED)) { return true; } else { DialogHelper.showDialog(activity, "警告!", "无法访问任何合适的存储空间"); return false; } } public static Object getStaticObjectFieldSilently(Class clazz, String fieldName) { try { return XposedHelpers.getStaticObjectField(clazz, fieldName); } catch (Throwable t) { return null; } } public static class MimeType { public static int IMAGE = 1; public static int AUDIO = 2; public static int VIDEO = 4; public static int DOCUMENT = 8; public static int ARCHIVE = 16; public static int LINK = 32; public static int OTHERS = 64; public static int ALL = IMAGE | AUDIO | VIDEO | DOCUMENT | ARCHIVE | LINK | OTHERS; } public static boolean isDackMode(Context context) { return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; } @SuppressLint("DiscouragedApi") public static int getSystemBackgroundColor(Context context) { int black = Color.BLACK; int white = Color.WHITE; try { black = context.getResources().getColor(context.getResources().getIdentifier("black", "color", "miui"), context.getTheme()); white = context.getResources().getColor(context.getResources().getIdentifier("white", "color", "miui"), context.getTheme()); } catch (Throwable ignore) { } return isDackMode(context) ? black : white; } public static Object proxySystemProperties(String method, String prop, int val, ClassLoader classLoader) { return XposedHelpers.callStaticMethod(XposedHelpers.findClassIfExists("android.os.SystemProperties", classLoader), method, prop, val); } public static void applyShimmer(TextView title) { if (title.getPaint().getShader() != null) return; int width = title.getResources().getDisplayMetrics().widthPixels; Shader shimmer = new LinearGradient(0, 0, width, 0, new int[]{0xFF5DA5FF, 0xFF9B8AFB, 0xFFD176F2, 0xFFFE88B2, 0xFFD176F2, 0xFF9B8AFB}, new float[]{0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f}, Shader.TileMode.REPEAT); Matrix matrix = new Matrix(); matrix.setTranslate(0, 0); shimmer.setLocalMatrix(matrix); title.getPaint().setShader(shimmer); } // Permissions 权限 @SuppressLint({"SetWorldReadable", "SetWorldWritable"}) public static void fixPermissionsAsync(Context context) { Executor executor = Executors.newSingleThreadExecutor(); executor.execute(() -> { try { Thread.sleep(500); } catch (Throwable ignore) { } File pkgFolder = context.getDataDir(); if (pkgFolder.exists()) { pkgFolder.setExecutable(true, false); pkgFolder.setReadable(true, false); pkgFolder.setWritable(true, false); } File sharedPrefsFolder = new File(PrefsUtils.getSharedPrefsPath()); if (sharedPrefsFolder.exists()) { sharedPrefsFolder.setExecutable(true, false); sharedPrefsFolder.setReadable(true, false); sharedPrefsFolder.setWritable(true, false); } File sharedPrefsFile = new File(PrefsUtils.getSharedPrefsFile()); if (sharedPrefsFile.exists()) { sharedPrefsFile.setReadable(true, false); sharedPrefsFile.setExecutable(true, false); sharedPrefsFile.setWritable(true, false); } }); } private static String getCallerMethod() { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement el : stackTrace) if (el != null && el.getClassName().startsWith(mAppModulePkg + ".module")) return el.getMethodName(); return stackTrace[4].getMethodName(); } public static void hookMethod(Method method, MethodHook callback) { try { XposedBridge.hookMethod(method, callback); } catch (Throwable t) { LogI(getCallerMethod(), "Failed to hook " + method.getName() + " method"); } } public static Context findContext() { Context context = null; try { context = (Application) XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentApplication"); if (context == null) { Object currentActivityThread = XposedHelpers.callStaticMethod(XposedHelpers.findClass("android.app.ActivityThread", null), "currentActivityThread"); if (currentActivityThread != null) context = (Context) XposedHelpers.callMethod(currentActivityThread, "getSystemContext"); } } catch (Throwable ignore) { } return context; } public static synchronized Context getModuleContext(Context context) throws Throwable { return getModuleContext(context, null); } public static synchronized Context getModuleContext(Context context, Configuration config) throws Throwable { if (mModuleContext == null) mModuleContext = context.createPackageContext(mAppModulePkg, Context.CONTEXT_IGNORE_SECURITY).createDeviceProtectedStorageContext(); return config == null ? mModuleContext : mModuleContext.createConfigurationContext(config); } public static synchronized Resources getModuleRes(Context context) throws Throwable { Configuration config = context.getResources().getConfiguration(); Context moduleContext = getModuleContext(context); return (config == null ? moduleContext.getResources() : moduleContext.createConfigurationContext(config).getResources()); } public static ActivityOptions makeFreeformActivityOptions(Context context, String str) { ActivityOptions activityOptions; try { activityOptions = (ActivityOptions) ReflectUtils.callStaticObjectMethod(Class.forName("android.util.MiuiMultiWindowUtils"), ActivityOptions.class, "getActivityOptions", new Class[]{Context.class, String.class, Boolean.TYPE, Boolean.TYPE}, new Object[]{context, str, true, false}); } catch (Exception e) { LogD(TAG, "MiuiMultiWindowUtils getActivityOptions error", e); activityOptions = null; } if (activityOptions != null) { return activityOptions; } ActivityOptions makeBasic = ActivityOptions.makeBasic(); ReflectUtils.callObjectMethod("android.app.ActivityOptions", "setLaunchWindowingMode", new Class[]{int.class}, 5); Rect rect = (Rect) ReflectUtils.callObjectMethod("android.util.MiuiMultiWindowUtils", "getFreeformRect", new Class[]{Context.class}, new Object[]{context}); makeBasic.setLaunchBounds(rect); return makeBasic; } public static XC_MethodHook.Unhook findAndHookMethodUseUnhook(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback) { try { return XposedHelpers.findAndHookMethod(className, classLoader, methodName, parameterTypesAndCallback); } catch (Throwable t) { LogI(getCallerMethod(), "Failed to hook " + methodName + " method in " + className); return null; } } public static XC_MethodHook.Unhook findAndHookMethodUseUnhook(Class clazz, String methodName, Object... parameterTypesAndCallback) { try { return XposedHelpers.findAndHookMethod(clazz, methodName, parameterTypesAndCallback); } catch (Throwable t) { LogI(getCallerMethod(), "Failed to hook " + methodName + " method in " + clazz.getCanonicalName()); return null; } } public static void findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback) { try { XposedHelpers.findAndHookMethod(className, classLoader, methodName, parameterTypesAndCallback); LogI(getCallerMethod(), "Success to hook " + methodName + " method in " + className); } catch (Throwable t) { LogI(getCallerMethod(), "Failed to hook " + methodName + " method in " + className); } } public static void findAndHookMethod(Class clazz, String methodName, Object... parameterTypesAndCallback) { try { XposedHelpers.findAndHookMethod(clazz, methodName, parameterTypesAndCallback); } catch (Throwable t) { LogI(getCallerMethod(), "Failed to hook " + methodName + " method in " + clazz.getCanonicalName()); } } public static boolean findAndHookMethodSilently(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback) { try { XposedHelpers.findAndHookMethod(className, classLoader, methodName, parameterTypesAndCallback); LogI(getCallerMethod(), "Success to hook " + methodName + " method in " + className); return true; } catch (Throwable t) { return false; } } public static boolean findAndHookMethodSilently(Class clazz, String methodName, Object... parameterTypesAndCallback) { try { XposedHelpers.findAndHookMethod(clazz, methodName, parameterTypesAndCallback); LogI(getCallerMethod(), "Success to hook " + methodName + " method in " + clazz.getCanonicalName()); return true; } catch (Throwable t) { LogI(getCallerMethod(), "Failed to hook " + methodName + " method in " + clazz.getCanonicalName() + " Error: " + t); return false; } } public static void findAndHookConstructor(String className, ClassLoader classLoader, Object... parameterTypesAndCallback) { try { XposedHelpers.findAndHookConstructor(className, classLoader, parameterTypesAndCallback); LogI(getCallerMethod(), "Success to hook constructor in " + className); } catch (Throwable t) { LogI(getCallerMethod(), "Failed to hook constructor in " + className + " Error: " + t); } } public static void findAndHookConstructor(Class hookClass, Object... parameterTypesAndCallback) { try { XposedHelpers.findAndHookConstructor(hookClass, parameterTypesAndCallback); LogI(getCallerMethod(), "Success to hook constructor in " + hookClass); } catch (Throwable t) { LogI(getCallerMethod(), "Failed to hook constructor in " + hookClass + " Error: " + t); } } public static void hookAllMethods(String className, ClassLoader classLoader, String methodName, XC_MethodHook callback) { try { Class hookClass = XposedHelpers.findClassIfExists(className, classLoader); if (hookClass == null || XposedBridge.hookAllMethods(hookClass, methodName, callback).size() == 0) ; } catch (Throwable t) { LogD("hookAllMethods", className + " is abnormal", t); } } public static void hookAllMethods(Class hookClass, String methodName, XC_MethodHook callback) { try { if (XposedBridge.hookAllMethods(hookClass, methodName, callback).size() == 0) LogI(getCallerMethod(), "Failed to hook " + methodName + " method in " + hookClass.getCanonicalName()); } catch (Throwable t) { LogD("hookAllMethods", hookClass + " is abnormal", t); } } public static void hookAllConstructors(String className, ClassLoader classLoader, MethodHook callback) { try { Class hookClass = XposedHelpers.findClassIfExists(className, classLoader); if (hookClass == null || XposedBridge.hookAllConstructors(hookClass, callback).size() == 0) LogI(getCallerMethod(), "Failed to hook " + className + " constructor"); } catch (Throwable t) { LogD("hookAllConstructors", className + " is abnormal", t); } } public static void hookAllConstructors(Class hookClass, MethodHook callback) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { XposedLogUtils.logI(getCallerMethod(), "Success to hook " + hookClass.getPackageName() + "/" + hookClass.getCanonicalName() + " constructor"); } if (XposedBridge.hookAllConstructors(hookClass, callback).size() == 0) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { XposedLogUtils.logI(getCallerMethod(), "Failed to hook " + hookClass.getPackageName() + "/" + hookClass.getCanonicalName() + " constructor"); } } catch (Throwable t) { LogD("hookAllMethods", hookClass + " is abnormal", t); } } public static void hookAllMethodsSilently(String className, ClassLoader classLoader, String methodName, XC_MethodHook callback) { try { Class hookClass = XposedHelpers.findClassIfExists(className, classLoader); if (hookClass != null) { XposedBridge.hookAllMethods(hookClass, methodName, callback).size(); } } catch (Throwable t) { LogD("hookAllMethodsSilently", className + " is abnormal", t); } } public static boolean hookAllMethodsSilently(Class hookClass, String methodName, XC_MethodHook callback) { try { return hookClass != null && XposedBridge.hookAllMethods(hookClass, methodName, callback).size() > 0; } catch (Throwable t) { return false; } } public static class SharedPrefObserver extends ContentObserver { enum PrefType { Any, String, StringSet, Integer, Boolean } PrefType prefType; Context ctx; String prefName; String prefDefValueString; int prefDefValueInt; boolean prefDefValueBool; public SharedPrefObserver(Context context, android.os.Handler handler) { super(handler); ctx = context; prefType = PrefType.Any; registerObserver(); } public SharedPrefObserver(Context context, android.os.Handler handler, String name, String defValue) { super(handler); ctx = context; prefName = name; prefType = PrefType.String; prefDefValueString = defValue; registerObserver(); } public SharedPrefObserver(Context context, android.os.Handler handler, String name) { super(handler); ctx = context; prefName = name; prefType = PrefType.StringSet; registerObserver(); } public SharedPrefObserver(Context context, android.os.Handler handler, String name, int defValue) { super(handler); ctx = context; prefType = PrefType.Integer; prefName = name; prefDefValueInt = defValue; registerObserver(); } public SharedPrefObserver(Context context, Handler handler, String name, boolean defValue) { super(handler); ctx = context; prefType = PrefType.Boolean; prefName = name; prefDefValueBool = defValue; registerObserver(); } void registerObserver() { Uri uri = null; if (prefType == PrefType.String) uri = stringPrefToUri(prefName, prefDefValueString); else if (prefType == PrefType.StringSet) uri = stringSetPrefToUri(prefName); else if (prefType == PrefType.Integer) uri = intPrefToUri(prefName, prefDefValueInt); else if (prefType == PrefType.Boolean) uri = boolPrefToUri(prefName, prefDefValueBool); else if (prefType == PrefType.Any) uri = anyPrefToUri(); if (uri != null) ctx.getContentResolver().registerContentObserver(uri, prefType == PrefType.Any, this); } @Override public void onChange(boolean selfChange, Uri uri) { if (prefType == PrefType.Any) onChange(uri); else onChange(selfChange); } @Override public void onChange(boolean selfChange) { if (selfChange) return; if (prefType == PrefType.String) onChange(prefName, prefDefValueString); else if (prefType == PrefType.StringSet) onChange(prefName); else if (prefType == PrefType.Integer) onChange(prefName, prefDefValueInt); else if (prefType == PrefType.Boolean) onChange(prefName, prefDefValueBool); } public void onChange(Uri uri) { } public void onChange(String name) { } public void onChange(String name, String defValue) { } public void onChange(String name, int defValue) { } public void onChange(String name, boolean defValue) { } } @SuppressWarnings("unchecked") public static Set getSharedStringSetPref(Context context, String name) { Uri uri = stringSetPrefToUri(name); try { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor != null) { Set prefValue = new LinkedHashSet<>(); while (cursor.moveToNext()) { prefValue.add(cursor.getString(0)); } cursor.close(); return prefValue; } else { LogI("ContentResolver", "[" + name + "] Cursor fail: null"); } } catch (Throwable t) { XposedBridge.log(t); } LinkedHashSet empty = new LinkedHashSet<>(); if (BaseHook.mPrefsMap.containsKey(name)) { return (Set) BaseHook.mPrefsMap.getObject(name, empty); } else { return empty; } } public static int getSharedIntPref(Context context, String name, int defValue) { Uri uri = intPrefToUri(name, defValue); try { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor != null && cursor.moveToFirst()) { int prefValue = cursor.getInt(0); cursor.close(); return prefValue; } else LogI("ContentResolver", "[" + name + "] Cursor fail: " + cursor); } catch (Throwable t) { XposedBridge.log(t); } if (BaseHook.mPrefsMap.containsKey(name)) return (int) BaseHook.mPrefsMap.getObject(name, defValue); else return defValue; } public static boolean getSharedBoolPref(Context context, String name, boolean defValue) { Uri uri = boolPrefToUri(name, defValue); try { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor != null && cursor.moveToFirst()) { int prefValue = cursor.getInt(0); cursor.close(); return prefValue == 1; } else LogI("ContentResolver", "[" + name + "] Cursor fail: " + cursor); } catch (Throwable t) { LogD("ContentResolver", t); } if (BaseHook.mPrefsMap.containsKey(name)) return (boolean) BaseHook.mPrefsMap.getObject(name, false); else return defValue; } public static Uri stringPrefToUri(String name, String defValue) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/string/" + name + "/" + defValue); } public static Uri stringSetPrefToUri(String name) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/stringset/" + name); } public static Uri intPrefToUri(String name, int defValue) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/integer/" + name + "/" + defValue); } public static Uri boolPrefToUri(String name, boolean defValue) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/boolean/" + name + "/" + (defValue ? '1' : '0')); } public static Uri shortcutIconPrefToUri(String name) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/shortcut_icon/" + name); } public static Uri anyPrefToUri() { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/pref/"); } public static class MethodHook extends XC_MethodHook { protected void before(MethodHookParam param) throws Throwable { } protected void after(MethodHookParam param) throws Throwable { } public MethodHook() { super(); } public MethodHook(int priority) { super(priority); } @Override public final void beforeHookedMethod(MethodHookParam param) throws Throwable { try { this.before(param); } catch (Throwable t) { LogD("beforeHook", t); } } @Override public final void afterHookedMethod(MethodHookParam param) throws Throwable { try { this.after(param); } catch (Throwable t) { LogD("afterHook", t); } } } public static String getPackageVersionName(XC_LoadPackage.LoadPackageParam lpparam) { try { Class parserCls = XposedHelpers.findClass("android.content.pm.PackageParser", lpparam.classLoader); Object parser = parserCls.newInstance(); File apkPath = new File(lpparam.appInfo.sourceDir); Object pkg = XposedHelpers.callMethod(parser, "parsePackage", apkPath, 0); String versionName = (String) XposedHelpers.getObjectField(pkg, "mVersionName"); XposedLogUtils.logI("getPackageVersionName", lpparam + " versionName is " + versionName); return versionName; } catch (Throwable e) { XposedLogUtils.logW("getPackageVersionName", e); return "null"; } } public static int getPackageVersionCode(XC_LoadPackage.LoadPackageParam lpparam) { try { Class parserCls = XposedHelpers.findClass("android.content.pm.PackageParser", lpparam.classLoader); Object parser = parserCls.newInstance(); File apkPath = new File(lpparam.appInfo.sourceDir); Object pkg = XposedHelpers.callMethod(parser, "parsePackage", apkPath, 0); int versionCode = XposedHelpers.getIntField(pkg, "mVersionCode"); XposedLogUtils.logI("getPackageVersionCode", lpparam + " versionCode is " + versionCode); return versionCode; } catch (Throwable e) { XposedLogUtils.logW("getPackageVersionCode", e); return -1; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/HookUtils.kt ================================================ package com.sevtinge.cemiuiler.utils import android.content.Context import android.graphics.drawable.Drawable import android.os.Build import android.view.View import androidx.annotation.RequiresApi import com.sevtinge.cemiuiler.utils.log.XposedLogUtils import com.sevtinge.cemiuiler.utils.log.XposedLogUtils.logE import com.sevtinge.cemiuiler.utils.log.XposedLogUtils.logW import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedHelpers object HookUtils { fun dip2px(context: Context, dpValue: Float): Float { val scale = context.resources.displayMetrics.density return dpValue * scale + 0.5f } fun getClass(className: String, classLoader: ClassLoader): Class<*>? { val result = XposedHelpers.findClassIfExists( className, classLoader ) if (result == null) { logE("getClass", "'$className' is NOT found.") } return result } fun replaceMethodResult( className: String, classLoader: ClassLoader, methodName: String, result: Any, vararg args: Any? ) { try { XposedHelpers.findAndHookMethod( className, classLoader, methodName, *args, XC_MethodReplacement.returnConstant(result) ) } catch (e: Throwable) { logW("replaceMethodResult", e) } } fun getValueByField(target: Any, fieldName: String, clazz: Class<*>? = null): Any? { var targetClass = clazz if (targetClass == null) { targetClass = target.javaClass } return try { val field = targetClass.getDeclaredField(fieldName) field.isAccessible = true field.get(target) } catch (e: Throwable) { if (targetClass.superclass == null) { null } else { getValueByField(target, fieldName, targetClass.superclass) } } } @RequiresApi(Build.VERSION_CODES.S) fun createBlurDrawable( view: View, blurRadius: Int, cornerRadius: Int, color: Int? = null ): Drawable? { try { val mViewRootImpl = XposedHelpers.callMethod(view, "getViewRootImpl") ?: return null val blurDrawable = XposedHelpers.callMethod(mViewRootImpl, "createBackgroundBlurDrawable") as Drawable XposedHelpers.callMethod(blurDrawable, "setBlurRadius", blurRadius) XposedHelpers.callMethod(blurDrawable, "setCornerRadius", cornerRadius) if (color != null) { XposedHelpers.callMethod(blurDrawable, "setColor",color) } return blurDrawable } catch (e: Throwable) { logW("createBlurDrawable", "Create BlurDrawable Error", e) return null } } fun isBlurDrawable(drawable: Drawable?): Boolean { // 不够严谨,可以用 if (drawable == null) { return false } val drawableClassName = drawable.javaClass.name return drawableClassName.contains("BackgroundBlurDrawable") } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/KotlinXposedHelper.kt ================================================ @file:Suppress("unused") package com.sevtinge.cemiuiler.utils import android.annotation.SuppressLint import android.content.res.XResources import com.github.kyuubiran.ezxhelper.EzXHelper.classLoader import com.github.kyuubiran.ezxhelper.Log import dalvik.system.BaseDexClassLoader import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XC_MethodHook.MethodHookParam import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedBridge.* import de.robv.android.xposed.XposedHelpers.* import de.robv.android.xposed.callbacks.XC_LayoutInflated import java.io.BufferedReader import java.io.DataOutputStream import java.io.IOException import java.io.InputStreamReader import java.lang.reflect.Field import java.lang.reflect.Member import java.lang.reflect.Modifier import java.util.Enumeration typealias MethodHookParam = MethodHookParam typealias Replacer = (MethodHookParam) -> Any? typealias Hooker = (MethodHookParam) -> Unit fun Class<*>.hookMethod(method: String?, vararg args: Any?) = try { findAndHookMethod(this, method, *args) } catch (e: NoSuchMethodError) { Log.e(e) null } catch (e: ClassNotFoundError) { Log.e(e) null } catch (e: ClassNotFoundException) { Log.e(e) null } fun Member.hookMethod(callback: XC_MethodHook) = try { hookMethod(this, callback) } catch (e: Throwable) { Log.e(e) null } inline fun MethodHookParam.callHooker(crossinline hooker: Hooker) = try { hooker(this) } catch (e: Throwable) { Log.e("Error occurred calling hooker on ${this.method}") Log.e(e) } inline fun MethodHookParam.callReplacer(crossinline replacer: Replacer) = try { replacer(this) } catch (e: Throwable) { Log.e("Error occurred calling replacer on ${this.method}") Log.e(e) null } inline fun Member.replaceMethod(crossinline replacer: Replacer) = hookMethod(object : XC_MethodReplacement() { override fun replaceHookedMethod(param: MethodHookParam) = param.callReplacer(replacer) }) inline fun Member.hookAfterMethod(crossinline hooker: Hooker) = hookMethod(object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Member.hookBeforeMethod(crossinline hooker: (MethodHookParam) -> Unit) = hookMethod(object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Class<*>.hookBeforeMethod( method: String?, vararg args: Any?, crossinline hooker: Hooker ) = hookMethod(method, *args, object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Class<*>.hookAfterMethod( method: String?, vararg args: Any?, crossinline hooker: Hooker ) = hookMethod(method, *args, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Class<*>.replaceMethod( method: String?, vararg args: Any?, crossinline replacer: Replacer ) = hookMethod(method, *args, object : XC_MethodReplacement() { override fun replaceHookedMethod(param: MethodHookParam) = param.callReplacer(replacer) }) fun Class<*>.hookAllMethods(methodName: String?, hooker: XC_MethodHook): Set = try { hookAllMethods(this, methodName, hooker) } catch (e: NoSuchMethodError) { Log.e(e) emptySet() } catch (e: ClassNotFoundError) { Log.e(e) emptySet() } catch (e: ClassNotFoundException) { Log.e(e) emptySet() } inline fun Class<*>.hookBeforeAllMethods(methodName: String?, crossinline hooker: Hooker) = hookAllMethods(methodName, object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Class<*>.hookAfterAllMethods(methodName: String?, crossinline hooker: Hooker) = hookAllMethods(methodName, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Class<*>.replaceAllMethods(methodName: String?, crossinline replacer: Replacer) = hookAllMethods(methodName, object : XC_MethodReplacement() { override fun replaceHookedMethod(param: MethodHookParam) = param.callReplacer(replacer) }) fun Class<*>.hookConstructor(vararg args: Any?) = try { findAndHookConstructor(this, *args) } catch (e: NoSuchMethodError) { Log.e(e) null } catch (e: ClassNotFoundError) { Log.e(e) null } catch (e: ClassNotFoundException) { Log.e(e) null } inline fun Class<*>.hookBeforeConstructor(vararg args: Any?, crossinline hooker: Hooker) = hookConstructor(*args, object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Class<*>.hookAfterConstructor(vararg args: Any?, crossinline hooker: Hooker) = hookConstructor(*args, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Class<*>.replaceConstructor(vararg args: Any?, crossinline hooker: Hooker) = hookConstructor(*args, object : XC_MethodReplacement() { override fun replaceHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) fun Class<*>.hookAllConstructors(hooker: XC_MethodHook): Set = try { hookAllConstructors(this, hooker) } catch (e: NoSuchMethodError) { Log.e(e) emptySet() } catch (e: ClassNotFoundError) { Log.e(e) emptySet() } catch (e: ClassNotFoundException) { Log.e(e) emptySet() } inline fun Class<*>.hookAfterAllConstructors(crossinline hooker: Hooker) = hookAllConstructors(object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Class<*>.hookBeforeAllConstructors(crossinline hooker: Hooker) = hookAllConstructors(object : XC_MethodHook() { override fun beforeHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) inline fun Class<*>.replaceAllConstructors(crossinline hooker: Hooker) = hookAllConstructors(object : XC_MethodReplacement() { override fun replaceHookedMethod(param: MethodHookParam) = param.callHooker(hooker) }) fun String.hookMethod( method: String?, vararg args: Any? ) = try { findClass().hookMethod(method, *args) } catch (e: ClassNotFoundError) { Log.e(e) null } catch (e: ClassNotFoundException) { Log.e(e) null } inline fun String.hookBeforeMethod( method: String?, vararg args: Any?, crossinline hooker: Hooker ) = try { findClass().hookBeforeMethod(method, *args, hooker = hooker) } catch (e: ClassNotFoundError) { Log.e(e) null } catch (e: ClassNotFoundException) { Log.e(e) null } inline fun String.hookAfterMethod( method: String?, vararg args: Any?, crossinline hooker: Hooker ) = try { findClass().hookAfterMethod(method, *args, hooker = hooker) } catch (e: ClassNotFoundError) { Log.e(e) null } catch (e: ClassNotFoundException) { Log.e(e) null } inline fun String.replaceMethod( method: String?, vararg args: Any?, crossinline replacer: Replacer ) = try { findClass().replaceMethod(method, *args, replacer = replacer) } catch (e: ClassNotFoundError) { Log.e(e) null } catch (e: ClassNotFoundException) { Log.e(e) null } fun MethodHookParam.invokeOriginalMethod(): Any? = invokeOriginalMethod(method, thisObject, args) inline fun T.runCatchingOrNull(func: T.() -> R?) = try { func() } catch (e: Throwable) { null } fun Any.getObjectField(field: String?): Any? = getObjectField(this, field) fun Any.getObjectFieldOrNull(field: String?): Any? = runCatchingOrNull { getObjectField(this, field) } @Suppress("UNCHECKED_CAST") fun Any.getObjectFieldAs(field: String?) = getObjectField(this, field) as T @Suppress("UNCHECKED_CAST") fun Any.getObjectFieldOrNullAs(field: String?) = runCatchingOrNull { getObjectField(this, field) as T } fun Any.getIntField(field: String?) = getIntField(this, field) fun Any.getIntFieldOrNull(field: String?) = runCatchingOrNull { getIntField(this, field) } fun Any.getLongField(field: String?) = getLongField(this, field) fun Any.getLongFieldOrNull(field: String?) = runCatchingOrNull { getLongField(this, field) } fun Any.getBooleanField(field: String?) = getBooleanField(this, field) fun Any.getBooleanFieldOrNull(field: String?) = runCatchingOrNull { getBooleanField(this, field) } fun Any.callMethod(methodName: String?, vararg args: Any?): Any? = callMethod(this, methodName, *args) fun Any.callMethodOrNull(methodName: String?, vararg args: Any?): Any? = runCatchingOrNull { callMethod(this, methodName, *args) } fun Class<*>.callStaticMethod(methodName: String?, vararg args: Any?): Any? = callStaticMethod(this, methodName, *args) fun Class<*>.callStaticMethodOrNull(methodName: String?, vararg args: Any?): Any? = runCatchingOrNull { callStaticMethod(this, methodName, *args) } @Suppress("UNCHECKED_CAST") fun Class<*>.callStaticMethodAs(methodName: String?, vararg args: Any?) = callStaticMethod(this, methodName, *args) as T @Suppress("UNCHECKED_CAST") fun Class<*>.callStaticMethodOrNullAs(methodName: String?, vararg args: Any?) = runCatchingOrNull { callStaticMethod(this, methodName, *args) as T } @Suppress("UNCHECKED_CAST") fun Class<*>.getStaticObjectFieldAs(field: String?) = getStaticObjectField(this, field) as T @Suppress("UNCHECKED_CAST") fun Class<*>.getStaticObjectFieldOrNullAs(field: String?) = runCatchingOrNull { getStaticObjectField(this, field) as T } fun Class<*>.getStaticObjectField(field: String?): Any? = getStaticObjectField(this, field) fun Class<*>.getStaticObjectFieldOrNull(field: String?): Any? = runCatchingOrNull { getStaticObjectField(this, field) } fun Class<*>.setStaticObjectField(field: String?, obj: Any?) = apply { setStaticObjectField(this, field, obj) } fun Class<*>.setStaticObjectFieldIfExist(field: String?, obj: Any?) = apply { try { setStaticObjectField(this, field, obj) } catch (ignored: Throwable) { } } inline fun Class<*>.findFieldByExactType(): Field? = findFirstFieldByExactType(this, T::class.java) fun Class<*>.findFieldByExactType(type: Class<*>): Field? = findFirstFieldByExactType(this, type) @Suppress("UNCHECKED_CAST") fun Any.callMethodAs(methodName: String?, vararg args: Any?) = callMethod(this, methodName, *args) as T @Suppress("UNCHECKED_CAST") fun Any.callMethodOrNullAs(methodName: String?, vararg args: Any?) = runCatchingOrNull { callMethod(this, methodName, *args) as T } fun Any.callMethod(methodName: String?, parameterTypes: Array>, vararg args: Any?): Any? = callMethod(this, methodName, parameterTypes, *args) fun Any.callMethodOrNull( methodName: String?, parameterTypes: Array>, vararg args: Any? ): Any? = runCatchingOrNull { callMethod(this, methodName, parameterTypes, *args) } fun Class<*>.callStaticMethod( methodName: String?, parameterTypes: Array>, vararg args: Any? ): Any? = callStaticMethod(this, methodName, parameterTypes, *args) fun Class<*>.callStaticMethodOrNull( methodName: String?, parameterTypes: Array>, vararg args: Any? ): Any? = runCatchingOrNull { callStaticMethod(this, methodName, parameterTypes, *args) } fun String.findClass(): Class<*> = findClass(this, classLoader) fun String.findClassOrNull(): Class<*>? = findClassIfExists(this, classLoader) fun Class<*>.new(vararg args: Any?): Any = newInstance(this, *args) fun Class<*>.new(parameterTypes: Array>, vararg args: Any?): Any = newInstance(this, parameterTypes, *args) fun Class<*>.findField(field: String?): Field = findField(this, field) fun Class<*>.findFieldOrNull(field: String?): Field? = findFieldIfExists(this, field) data class ResourcesHookData(val type: String, val afterValue: Any) class ResourcesHookMap : HashMap() { fun isKeyExist(key: String): Boolean = getOrDefault(key, null) != null } fun T.setIntField(field: String?, value: Int) = apply { setIntField(this, field, value) } fun T.setLongField(field: String?, value: Long) = apply { setLongField(this, field, value) } fun T.setFloatField(field: String?, value: Float) = apply { setFloatField(this, field, value) } fun T.setBooleanField(field: String?, value: Boolean) = apply { setBooleanField(this, field, value) } fun T.setObjectField(field: String?, value: Any?) = apply { setObjectField(this, field, value) } inline fun XResources.hookLayout( id: Int, crossinline hooker: (XC_LayoutInflated.LayoutInflatedParam) -> Unit ) { try { hookLayout(id, object : XC_LayoutInflated() { override fun handleLayoutInflated(liparam: LayoutInflatedParam) { try { hooker(liparam) } catch (e: Throwable) { Log.e(e) } } }) } catch (e: Throwable) { Log.e(e) } } @SuppressLint("DiscouragedApi") inline fun XResources.hookLayout( pkg: String, type: String, name: String, crossinline hooker: (XC_LayoutInflated.LayoutInflatedParam) -> Unit ) { try { val id = getIdentifier(name, type, pkg) hookLayout(id, hooker) } catch (e: Throwable) { Log.e(e) } } fun Class<*>.findFirstFieldByExactType(type: Class<*>): Field = findFirstFieldByExactType(this, type) fun Class<*>.findFirstFieldByExactTypeOrNull(type: Class<*>?): Field? = runCatchingOrNull { findFirstFieldByExactType(this, type) } fun Any.getFirstFieldByExactType(type: Class<*>): Any? = javaClass.findFirstFieldByExactType(type).get(this) @Suppress("UNCHECKED_CAST") fun Any.getFirstFieldByExactTypeAs(type: Class<*>) = javaClass.findFirstFieldByExactType(type).get(this) as? T inline fun Any.getFirstFieldByExactType() = javaClass.findFirstFieldByExactType(T::class.java).get(this) as? T fun Any.getFirstFieldByExactTypeOrNull(type: Class<*>?): Any? = runCatchingOrNull { javaClass.findFirstFieldByExactTypeOrNull(type)?.get(this) } @Suppress("UNCHECKED_CAST") fun Any.getFirstFieldByExactTypeOrNullAs(type: Class<*>?) = getFirstFieldByExactTypeOrNull(type) as? T inline fun Any.getFirstFieldByExactTypeOrNull() = getFirstFieldByExactTypeOrNull(T::class.java) as? T inline fun ClassLoader.findDexClassLoader(crossinline delegator: (BaseDexClassLoader) -> BaseDexClassLoader = { x -> x }): BaseDexClassLoader? { var classLoader = this while (classLoader !is BaseDexClassLoader) { if (classLoader.parent != null) classLoader = classLoader.parent else return null } return delegator(classLoader) } inline fun ClassLoader.allClassesList(crossinline delegator: (BaseDexClassLoader) -> BaseDexClassLoader = { x -> x }): List { return findDexClassLoader(delegator)?.getObjectField("pathList")?.getObjectFieldAs>("dexElements") ?.flatMap { it.getObjectField("dexFile")?.callMethodAs>("entries")?.toList().orEmpty() }.orEmpty() } fun exec(command: String): String { var process: Process? = null var reader: BufferedReader? = null var `is`: InputStreamReader? = null var os: DataOutputStream? = null return try { process = Runtime.getRuntime().exec("su") `is` = InputStreamReader(process.inputStream) reader = BufferedReader(`is`) os = DataOutputStream(process.outputStream) os.writeBytes( command.trimIndent() ) os.writeBytes("\nexit\n") os.flush() var read: Int val buffer = CharArray(4096) val output = StringBuilder() while (reader.read(buffer).also { read = it } > 0) { output.appendRange(buffer, 0, read) } process.waitFor() output.toString() } catch (e: IOException) { throw RuntimeException(e) } catch (e: InterruptedException) { throw RuntimeException(e) } finally { try { os?.close() `is`?.close() reader?.close() process?.destroy() } catch (e: IOException) { e.printStackTrace() } } } fun exec(commands: Array): String { val stringBuilder = java.lang.StringBuilder() for (command in commands) { stringBuilder.append(exec(command)) stringBuilder.append("\n") } return stringBuilder.toString() } val Member.isStatic: Boolean inline get() = Modifier.isStatic(modifiers) val Member.isFinal: Boolean inline get() = Modifier.isFinal(modifiers) val Member.isPublic: Boolean inline get() = Modifier.isPublic(modifiers) val Member.isNotStatic: Boolean inline get() = !isStatic val Class<*>.isAbstract: Boolean inline get() = !isPrimitive && Modifier.isAbstract(modifiers) ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/LogcatHelper.java ================================================ package com.sevtinge.cemiuiler.utils; import android.annotation.SuppressLint; import android.content.Context; import android.os.Environment; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.Date; public class LogcatHelper { private static LogcatHelper INSTANCE = null; private static String PATH_LOGCAT; private LogDumper mLogDumper = null; private final int mPId; /** * 初始化目录 */ public void init(Context context) { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { // 优先保存到SD卡中 PATH_LOGCAT = context.getExternalCacheDir().getAbsolutePath(); } else {// 如果SD卡不存在,就保存到本应用的目录下 PATH_LOGCAT = context.getFilesDir().getAbsolutePath() + File.separator; } File file = new File(PATH_LOGCAT); if (!file.exists()) { file.mkdirs(); } } public static LogcatHelper getInstance(Context context) { if (INSTANCE == null) { INSTANCE = new LogcatHelper(context); } return INSTANCE; } private LogcatHelper(Context context) { init(context); mPId = android.os.Process.myPid(); } public void start() { if (mLogDumper == null) mLogDumper = new LogDumper(String.valueOf(mPId), PATH_LOGCAT); mLogDumper.start(); } public void stop() { if (mLogDumper != null) { mLogDumper.stopLogs(); mLogDumper = null; } } private static class LogDumper extends Thread { private Process logcatProc; private BufferedReader mReader = null; private boolean mRunning = true; String cmds = null; private final String mPID; private FileOutputStream out = null; public LogDumper(String pid, String dir) { mPID = pid; try { out = new FileOutputStream(new File(dir, "Cemiuiler_" + getFileName() + ".log")); } catch (FileNotFoundException e) { e.printStackTrace(); } /* 日志等级:*:v , *:d , *:w , *:e , *:f , *:s

显示当前mPID程序的 E和W等级的日志.

*/ // cmds = "logcat *:e *:w | grep \"(" + mPID + ")\""; // cmds = "logcat | grep \"(" + mPID + ")\"";//打印所有日志信息 // cmds = "logcat -s way";//打印标签过滤信息 // cmds = "logcat *:e *:i | grep \"(" + mPID + ")\""; cmds = "logcat *:i | grep \"(" + mPID + ")\""; } public void stopLogs() { mRunning = false; } @Override public void run() { try { logcatProc = Runtime.getRuntime().exec(cmds); mReader = new BufferedReader(new InputStreamReader(logcatProc.getInputStream()), 1024); String line = null; while (mRunning && (line = mReader.readLine()) != null) { if (!mRunning) { break; } if (line.length() == 0) { continue; } if (out != null && line.contains(mPID)) { out.write((getDateEN() + " " + line + "\n") .getBytes()); } } } catch (IOException e) { e.printStackTrace(); } finally { if (logcatProc != null) { logcatProc.destroy(); logcatProc = null; } if (mReader != null) { try { mReader.close(); mReader = null; } catch (IOException e) { e.printStackTrace(); } } if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } out = null; } } } } @SuppressLint("SimpleDateFormat") public static String getFileName() { SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd"); return format.format(new Date(System.currentTimeMillis())); } @SuppressLint("SimpleDateFormat") public static String getDateEN() { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return format.format(new Date(System.currentTimeMillis())); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/MathUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import android.annotation.SuppressLint; import android.graphics.Rect; import com.sevtinge.cemiuiler.utils.log.AndroidLogUtils; import java.lang.reflect.Method; public class MathUtils { private static final float DEG_TO_RAD = 0.017453292f; private static final float RAD_TO_DEG = 57.295784f; private MathUtils() { } public static float abs(float v) { return v > 0.0f ? v : -v; } public static int constrain(int amount, int low, int high) { return amount < low ? low : Math.min(amount, high); } public static long constrain(long amount, long low, long high) { return amount < low ? low : Math.min(amount, high); } public static float constrain(float amount, float low, float high) { return amount < low ? low : Math.min(amount, high); } public static float log(float a) { return (float) Math.log(a); } public static float exp(float a) { return (float) Math.exp(a); } public static float pow(float a, float b) { return (float) Math.pow(a, b); } public static float sqrt(float a) { return (float) Math.sqrt(a); } public static float max(float a, float b) { return Math.max(a, b); } public static float max(int a, int b) { return Math.max(a, b); } public static float max(float a, float b, float c) { if (a > b) { if (a > c) { return a; } } else if (b > c) { return b; } return c; } public static float max(int a, int b, int c) { int i; if (a > b) { i = Math.max(a, c); } else { i = Math.max(b, c); } return i; } public static float min(float a, float b) { return Math.min(a, b); } public static float min(int a, int b) { return Math.min(a, b); } public static float min(float a, float b, float c) { if (a < b) { if (a < c) { return a; } } else if (b < c) { return b; } return c; } public static float min(int a, int b, int c) { int i; if (a < b) { i = Math.min(a, c); } else { i = Math.min(b, c); } return i; } public static float dist(float x1, float y1, float x2, float y2) { float x = x2 - x1; float y = y2 - y1; return (float) Math.hypot(x, y); } public static float dist(float x1, float y1, float z1, float x2, float y2, float z2) { float x = x2 - x1; float y = y2 - y1; float z = z2 - z1; return (float) Math.sqrt((x * x) + (y * y) + (z * z)); } public static float mag(float a, float b) { return (float) Math.hypot(a, b); } public static float mag(float a, float b, float c) { return (float) Math.sqrt((a * a) + (b * b) + (c * c)); } public static float sq(float v) { return v * v; } public static float dot(float v1x, float v1y, float v2x, float v2y) { return (v1x * v2x) + (v1y * v2y); } public static float cross(float v1x, float v1y, float v2x, float v2y) { return (v1x * v2y) - (v1y * v2x); } public static float radians(float degrees) { return DEG_TO_RAD * degrees; } public static float degrees(float radians) { return RAD_TO_DEG * radians; } public static float acos(float value) { return (float) Math.acos(value); } public static float asin(float value) { return (float) Math.asin(value); } public static float atan(float value) { return (float) Math.atan(value); } public static float atan2(float a, float b) { return (float) Math.atan2(a, b); } public static float tan(float angle) { return (float) Math.tan(angle); } public static float lerp(float start, float stop, float amount) { return ((stop - start) * amount) + start; } public static float lerpNew(float start, float stop, float amount) { int value = Math.round((((stop - start) * amount) + start)); return Math.min(value, stop); } public static float lerp(int start, int stop, float amount) { return lerp(start, stop, amount); } public static float lerpInv(float a, float b, float value) { if (a != b) { return (value - a) / (b - a); } return 0.0f; } public static float saturate(float value) { return constrain(value, 0.0f, 1.0f); } public static float lerpInvSat(float a, float b, float value) { return saturate(lerpInv(a, b, value)); } public static float lerpDeg(float start, float end, float amount) { float minAngle = (((end - start) + 180.0f) % 360.0f) - 180.0f; return (minAngle * amount) + start; } public static float norm(float start, float stop, float value) { return (value - start) / (stop - start); } public static float map(float minStart, float minStop, float maxStart, float maxStop, float value) { return ((maxStop - maxStart) * ((value - minStart) / (minStop - minStart))) + maxStart; } public static float constrainedMap(float rangeMin, float rangeMax, float valueMin, float valueMax, float value) { return lerp(rangeMin, rangeMax, lerpInvSat(valueMin, valueMax, value)); } public static float smoothStep(float start, float end, float x) { return constrain((x - start) / (end - start), 0.0f, 1.0f); } public static int addOrThrow(int a, int b) throws IllegalArgumentException { if (b == 0) { return a; } if (b > 0 && a <= Integer.MAX_VALUE - b) { return a + b; } if (b < 0 && a >= Integer.MIN_VALUE - b) { return a + b; } throw new IllegalArgumentException("Addition overflow: " + a + " + " + b); } public static float convertGammaToLinearFloat(float i, int max, float f, float f2) { float norm = norm(0.0f, max, i); float R = 0.4f; float A = 0.2146f; float B = 0.2847f; float C = 0.4719f; return lerp(f, f2, constrain(norm <= R ? sq(norm / R) : exp((norm - C) / A) + B, 0.0f, 12.0f) / 12.0f); } public static void fitRect(Rect outToResize, int largestSide) { if (outToResize.isEmpty()) { return; } float maxSize = Math.max(outToResize.width(), outToResize.height()); try { Class rectClass = Class.forName("android.graphics.Rect"); // 获取带有 @hide 注解的方法名称 String methodName = "scale"; // 获取方法 @SuppressLint("DiscouragedPrivateApi") Method scaleMethod = rectClass.getDeclaredMethod(methodName, float.class); // 创建一个 Rect 实例 Rect rectInstance = new Rect(outToResize); // 设置方法可访问(即强行访问) scaleMethod.setAccessible(true); // 调用带有 @hide 注解的方法 scaleMethod.invoke(rectInstance, largestSide / maxSize); } catch (Exception e) { AndroidLogUtils.LogE("Call Method scale error: ", e); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/PrefsMap.java ================================================ package com.sevtinge.cemiuiler.utils; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Set; public class PrefsMap extends HashMap { public Object getObject(String key, Object defValue) { return get(key) == null ? defValue : get(key); } public int getInt(String key, int defValue) { key = "prefs_key_" + key; return get(key) == null ? defValue : (Integer) get(key); } public String getString(String key, String defValue) { key = "prefs_key_" + key; return get(key) == null ? defValue : (String) get(key); } public int getStringAsInt(String key, int defValue) { key = "prefs_key_" + key; return get(key) == null ? defValue : Integer.parseInt((String) get(key)); } @SuppressWarnings("unchecked") public Set getStringSet(String key) { key = "prefs_key_" + key; return get(key) == null ? new LinkedHashSet<>() : (Set) get(key); } public boolean getBoolean(String key) { key = "prefs_key_" + key; return get(key) == null ? false : (Boolean) get(key); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/PrefsUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Handler; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.provider.SharedPrefsProvider; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import java.io.File; import java.lang.reflect.Field; import java.util.LinkedHashSet; import java.util.Set; import de.robv.android.xposed.XposedBridge; public class PrefsUtils { public static SharedPreferences mSharedPreferences = null; public static String mPrefsPathCurrent = null; public static String mPrefsFileCurrent = null; public static String mPrefsName = "cemiuiler_prefs"; public static String mPrefsPath = "/data/user_de/0/" + Helpers.mAppModulePkg + "/shared_prefs"; public static String mPrefsFile = mPrefsPath + "/" + mPrefsName + ".xml"; public static SharedPreferences getSharedPrefs(Context context, boolean multiProcess) { context = Helpers.getProtectedContext(context); try { return context.getSharedPreferences(mPrefsName, multiProcess ? Context.MODE_MULTI_PROCESS | Context.MODE_WORLD_READABLE : Context.MODE_WORLD_READABLE); } catch (Throwable t) { return context.getSharedPreferences(mPrefsName, multiProcess ? Context.MODE_MULTI_PROCESS | Context.MODE_PRIVATE : Context.MODE_PRIVATE); } } public static SharedPreferences getSharedPrefs(Context context) { return getSharedPrefs(context, false); } public static String getSharedPrefsPath() { if (mPrefsPathCurrent == null) try { Field mFile = mSharedPreferences.getClass().getDeclaredField("mFile"); mFile.setAccessible(true); mPrefsPathCurrent = ((File) mFile.get(mSharedPreferences)).getParentFile().getAbsolutePath(); return mPrefsPathCurrent; } catch (Throwable t) { System.out.print("Test" + t); return mPrefsPath; } else return mPrefsPathCurrent; } public static String getSharedPrefsFile() { if (mPrefsFileCurrent == null) try { Field fFile = mSharedPreferences.getClass().getDeclaredField("mFile"); fFile.setAccessible(true); mPrefsFileCurrent = ((File) fFile.get(mSharedPreferences)).getAbsolutePath(); System.out.println("Test: mPrefsFileCurrent"); return mPrefsFileCurrent; } catch (Throwable t) { System.out.println("Test: mPrefsFile" + t); return mPrefsFile; } else System.out.println("Test: mPrefsFileCurrent2"); return mPrefsFileCurrent; } public static boolean contains(String key) { return mSharedPreferences.contains(key); } public static SharedPreferences.Editor editor() { return mSharedPreferences.edit(); } public static String getSharedStringPrefs(Context context, String name, String defValue) { Uri uri = stringPrefsToUri(name, defValue); try { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor != null && cursor.moveToFirst()) { String prefValue = cursor.getString(0); cursor.close(); return prefValue; } else XposedLogUtils.logI("ContentResolver", "[" + name + "] Cursor fail: " + cursor); } catch (Throwable t) { XposedBridge.log(t); } if (XposedInit.mPrefsMap.containsKey(name)) return (String) XposedInit.mPrefsMap.getObject(name, defValue); else return defValue; } public static Set getSharedStringSetPrefs(Context context, String name) { Uri uri = stringSetPrefsToUri(name); try { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor != null) { Set prefValue = new LinkedHashSet<>(); while (cursor.moveToNext()) { prefValue.add(cursor.getString(0)); } cursor.close(); return prefValue; } else { XposedLogUtils.logI("ContentResolver", "[" + name + "] Cursor fail: null"); } } catch (Throwable t) { XposedBridge.log(t); } LinkedHashSet empty = new LinkedHashSet<>(); if (XposedInit.mPrefsMap.containsKey(name)) { return (Set) XposedInit.mPrefsMap.getObject(name, empty); } else { return empty; } } public static int getSharedIntPrefs(Context context, String name, int defValue) { Uri uri = intPrefsToUri(name, defValue); try { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor != null && cursor.moveToFirst()) { int prefValue = cursor.getInt(0); cursor.close(); return prefValue; } else XposedLogUtils.logI("ContentResolver", "[" + name + "] Cursor fail: " + cursor); } catch (Throwable t) { XposedBridge.log(t); } if (XposedInit.mPrefsMap.containsKey(name)) return (int) XposedInit.mPrefsMap.getObject(name, defValue); else return defValue; } public static boolean getSharedBoolPrefs(Context context, String name, boolean defValue) { Uri uri = boolPrefsToUri(name, defValue); try { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor != null && cursor.moveToFirst()) { int prefValue = cursor.getInt(0); cursor.close(); return prefValue == 1; } else XposedLogUtils.logI("ContentResolver", "[" + name + "] Cursor fail: " + cursor); } catch (Throwable t) { XposedBridge.log(t); } if (XposedInit.mPrefsMap.containsKey(name)) return (boolean) XposedInit.mPrefsMap.getObject(name, false); else return defValue; } public static Uri stringPrefsToUri(String name, String defValue) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/string/" + name + "/" + defValue); } public static Uri stringSetPrefsToUri(String name) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/stringset/" + name); } public static Uri intPrefsToUri(String name, int defValue) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/integer/" + name + "/" + defValue); } public static Uri boolPrefsToUri(String name, boolean defValue) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/boolean/" + name + "/" + (defValue ? '1' : '0')); } public static Uri shortcutIconPrefsToUri(String name) { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/shortcut_icon/" + name); } public static Uri anyPrefsToUri() { return Uri.parse("content://" + SharedPrefsProvider.AUTHORITY + "/pref/"); } public static class SharedPrefsObserver extends ContentObserver { enum PrefType { Any, String, StringSet, Integer, Boolean } PrefType prefType; Context ctx; String mPrefsName; String mPrefsDefValueString; int mPrefsDefValueInt; boolean mPrefsDefValueBool; public SharedPrefsObserver(Context context, Handler handler) { super(handler); ctx = context; prefType = PrefType.Any; registerObserver(); } public SharedPrefsObserver(Context context, Handler handler, String name, String defValue) { super(handler); ctx = context; mPrefsName = name; prefType = PrefType.String; mPrefsDefValueString = defValue; registerObserver(); } public SharedPrefsObserver(Context context, Handler handler, String name) { super(handler); ctx = context; mPrefsName = name; prefType = PrefType.StringSet; registerObserver(); } public SharedPrefsObserver(Context context, Handler handler, String name, int defValue) { super(handler); ctx = context; prefType = PrefType.Integer; mPrefsName = name; mPrefsDefValueInt = defValue; registerObserver(); } @SuppressLint("SuspiciousIndentation") public SharedPrefsObserver(Context context, Handler handler, String name, boolean defValue) { super(handler); ctx = context; prefType = PrefType.Boolean; mPrefsName = name; mPrefsDefValueBool = defValue; registerObserver(); } void registerObserver() { Uri uri = null; if (prefType == PrefType.String) uri = stringPrefsToUri(mPrefsName, mPrefsDefValueString); else if (prefType == PrefType.StringSet) uri = stringSetPrefsToUri(mPrefsName); else if (prefType == PrefType.Integer) uri = intPrefsToUri(mPrefsName, mPrefsDefValueInt); else if (prefType == PrefType.Boolean) uri = boolPrefsToUri(mPrefsName, mPrefsDefValueBool); else if (prefType == PrefType.Any) uri = anyPrefsToUri(); if (uri != null) ctx.getContentResolver().registerContentObserver(uri, prefType == PrefType.Any, this); } @Override public void onChange(boolean selfChange, Uri uri) { if (prefType == PrefType.Any) onChange(uri); else onChange(selfChange); } @Override public void onChange(boolean selfChange) { if (selfChange) return; if (prefType == PrefType.String) onChange(mPrefsName, mPrefsDefValueString); else if (prefType == PrefType.StringSet) onChange(mPrefsName); else if (prefType == PrefType.Integer) onChange(mPrefsName, mPrefsDefValueInt); else if (prefType == PrefType.Boolean) onChange(mPrefsName, mPrefsDefValueBool); } public void onChange(Uri uri) { } public void onChange(String name) { } public void onChange(String name, String defValue) { } public void onChange(String name, int defValue) { } public void onChange(String name, boolean defValue) { } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/PropertyUtils.kt ================================================ package com.sevtinge.cemiuiler.utils import android.annotation.SuppressLint import com.sevtinge.cemiuiler.utils.log.XposedLogUtils.logW import java.lang.reflect.Method object PropertyUtils { private val get: Method by lazy { @SuppressLint("PrivateApi") val cls = Class.forName("android.os.SystemProperties") cls.getDeclaredMethod("get", String::class.java, String::class.java) } operator fun get(prop: String, defaultValue: String?): String? { kotlin.runCatching { get.invoke(null, prop, defaultValue) as String? }.onFailure { logW("", it) }.onSuccess { return it } return defaultValue } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/ResourcesHook.java ================================================ package com.sevtinge.cemiuiler.utils; import static com.sevtinge.cemiuiler.utils.log.AndroidLogUtils.LogD; import android.content.Context; import android.content.res.Resources; import android.util.Pair; import android.util.SparseIntArray; import java.util.concurrent.ConcurrentHashMap; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; public class ResourcesHook { private boolean hooksApplied = false; public enum ReplacementType { ID, DENSITY, OBJECT } private final SparseIntArray fakes = new SparseIntArray(); private final ConcurrentHashMap> replacements = new ConcurrentHashMap<>(); public static int getFakeResId(String resourceName) { return 0x7e00f000 | (resourceName.hashCode() & 0x00ffffff); } private final Helpers.MethodHook mReplaceHook = new Helpers.MethodHook() { @Override protected void before(MethodHookParam param) { Context mContext = Helpers.findContext(); if (mContext == null) return; String method = param.method.getName(); Object value = getFakeResource(mContext, method, param.args); if (value == null) { value = getResourceReplacement(mContext, (Resources) param.thisObject, method, param.args); if (value == null) return; if ("getDimensionPixelOffset".equals(method) || "getDimensionPixelSize".equals(method)) { if (value instanceof Float) value = ((Float) value).intValue(); } } param.setResult(value); } }; public ResourcesHook() { } private void applyHooks() { if (hooksApplied) return; hooksApplied = true; Helpers.findAndHookMethod(Resources.class, "getInteger", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getLayout", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getFraction", int.class, int.class, int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getBoolean", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getDimension", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getDimensionPixelOffset", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getDimensionPixelSize", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getText", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getString", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getDrawableForDensity", int.class, int.class, Resources.Theme.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getIntArray", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getStringArray", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getTextArray", int.class, mReplaceHook); Helpers.findAndHookMethod(Resources.class, "getAnimation", int.class, mReplaceHook); } public int addResource(String resName, int resId) { try { applyHooks(); int fakeResId = getFakeResId(resName); fakes.put(fakeResId, resId); return fakeResId; } catch (Throwable t) { XposedBridge.log(t); return 0; } } private Object getFakeResource(Context context, String method, Object[] args) { try { if (context == null) return null; int modResId = fakes.get((int) args[0]); if (modResId == 0) return null; Object value; Resources modRes = Helpers.getModuleRes(context); if ("getDrawable".equals(method)) value = XposedHelpers.callMethod(modRes, method, modResId, args[1]); else if ("getDrawableForDensity".equals(method) || "getFraction".equals(method)) value = XposedHelpers.callMethod(modRes, method, modResId, args[1], args[2]); else value = XposedHelpers.callMethod(modRes, method, modResId); return value; } catch (Throwable t) { LogD("getFakeResource", t); return null; } } public void setResReplacement(String pkg, String type, String name, int replacementResId) { try { applyHooks(); replacements.put(pkg + ":" + type + "/" + name, new Pair<>(ReplacementType.ID, replacementResId)); } catch (Throwable t) { XposedBridge.log(t); } } public void setDensityReplacement(String pkg, String type, String name, float replacementResValue) { try { applyHooks(); replacements.put(pkg + ":" + type + "/" + name, new Pair<>(ReplacementType.DENSITY, replacementResValue)); } catch (Throwable t) { XposedBridge.log(t); } } public void setObjectReplacement(String pkg, String type, String name, Object replacementResValue) { try { applyHooks(); replacements.put(pkg + ":" + type + "/" + name, new Pair<>(ReplacementType.OBJECT, replacementResValue)); } catch (Throwable t) { XposedBridge.log(t); } } private Object getResourceReplacement(Context context, Resources res, String method, Object[] args) { if (context == null) return null; String pkgName = null; String resType = null; String resName = null; try { pkgName = res.getResourcePackageName((int) args[0]); resType = res.getResourceTypeName((int) args[0]); resName = res.getResourceEntryName((int) args[0]); } catch (Throwable ignore) { } if (pkgName == null || resType == null || resName == null) return null; try { Object value; String resFullName = pkgName + ":" + resType + "/" + resName; String resAnyPkgName = "*:" + resType + "/" + resName; Integer modResId = null; Pair replacement = null; if (replacements.containsKey(resFullName)) replacement = replacements.get(resFullName); else if (replacements.containsKey(resAnyPkgName)) replacement = replacements.get(resAnyPkgName); if (replacement != null) if (replacement.first == ReplacementType.OBJECT) return replacement.second; else if (replacement.first == ReplacementType.DENSITY) { return (Float) replacement.second * res.getDisplayMetrics().density; } else if (replacement.first == ReplacementType.ID) modResId = (Integer) replacement.second; if (modResId == null) return null; Resources modRes = Helpers.getModuleRes(context); if ("getDrawable".equals(method)) value = XposedHelpers.callMethod(modRes, method, modResId, args[1]); else if ("getDrawableForDensity".equals(method) || "getFraction".equals(method)) value = XposedHelpers.callMethod(modRes, method, modResId, args[1], args[2]); else value = XposedHelpers.callMethod(modRes, method, modResId); return value; } catch (Throwable t) { LogD("getResourceReplacement", t); return null; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/SearchHelper.java ================================================ package com.sevtinge.cemiuiler.utils; import static com.sevtinge.cemiuiler.utils.api.VoyagerApisKt.isPad; import android.content.Context; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.graphics.Color; import android.text.TextUtils; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.data.ModData; import org.xmlpull.v1.XmlPullParser; import java.util.ArrayList; import java.util.HashSet; import java.util.Objects; import java.util.Set; public class SearchHelper { public static final int MARK_COLOR_VIBRANT = Color.rgb(255, 0, 0); public static final String NEW_MODS_SEARCH_QUERY = "\uD83C\uDD95"; public static ArrayList allModsList = new ArrayList<>(); public static final HashSet NEW_MODS = new HashSet<>( Set.of( "pref_key_launcher_nozoomanim" ) ); public static final String ANDROID_NS = "http://schemas.android.com/apk/res/android"; public static final String MIUIZER_NS = "http://schemas.android.com/apk/res-auto"; public static void getAllMods(Context context, boolean force) { if (force) { allModsList.clear(); } else if (allModsList.size() > 0) { return; } // 系统框架页面相关 parsePrefXml(context, R.xml.framework_freeform, R.string.system_framework, R.string.floating_window, R.string.floating_window, R.string.floating_window, R.string.floating_window, "com.sevtinge.cemiuiler.ui.fragment.framework.FreeFormSettings"); parsePrefXml(context, R.xml.framework_volume, R.string.system_framework, R.string.system_framework_volume_title, R.string.system_framework_volume_title, R.string.system_framework_volume_title, R.string.system_framework_volume_title, "com.sevtinge.cemiuiler.ui.fragment.framework.VolumeSettings"); parsePrefXml(context, R.xml.framework_phone, R.string.system_framework, R.string.system_framework_phone_title, R.string.system_framework_phone_title, R.string.system_framework_phone_title, R.string.system_framework_phone_title, "com.sevtinge.cemiuiler.ui.fragment.framework.NetworkSettings"); parsePrefXml(context, R.xml.framework_display, R.string.system_framework, R.string.system_framework_display_title, R.string.system_framework_display_title, R.string.system_framework_display_title, R.string.system_framework_display_title, "com.sevtinge.cemiuiler.ui.fragment.framework.DisplaySettings"); parsePrefXml(context, R.xml.framework_other, R.string.system_framework, R.string.system_framework_other_title, R.string.system_framework_other_title, R.string.system_framework_other_title, R.string.system_framework_other_title, "com.sevtinge.cemiuiler.ui.fragment.framework.OtherSettings"); // 系统界面页面相关 parsePrefXml(context, R.xml.system_ui_lock_screen, R.string.system_ui, R.string.system_ui_lockscreen_title, R.string.system_ui_lockscreen_title, R.string.system_ui_lockscreen_title, R.string.system_ui_lockscreen_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.LockScreenSettings"); parsePrefXml(context, R.xml.system_ui_status_bar, R.string.system_ui, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.StatusBarSettings"); parsePrefXml(context, R.xml.system_ui_status_bar_icon_manage, R.string.system_ui, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_iconmanage_title, R.string.system_ui_statusbar_iconmanage_title, R.string.system_ui_statusbar_iconmanage_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar.IconManageSettings"); parsePrefXml(context, R.xml.system_ui_status_bar_mobile_network_type, R.string.system_ui, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_iconmanage_title, R.string.system_ui_status_bar_mobile_type_single_title, R.string.system_ui_status_bar_mobile_type_single_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar.MobileNetworkTypeSettings"); parsePrefXml(context, R.xml.system_ui_status_bar_doubleline_network, R.string.system_ui, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_iconmanage_title, R.string.system_ui_statusbar_iconmanage_mobile_network_title, R.string.system_ui_statusbar_iconmanage_mobile_network_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar.DoubleLineNetworkSettings"); parsePrefXml(context, R.xml.system_ui_status_bar_battery_styles, R.string.system_ui, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_iconmanage_title, R.string.system_ui_status_bar_battery_style_title, R.string.system_ui_status_bar_battery_style_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar.BatteryStyleSettings"); parsePrefXml(context, R.xml.system_ui_status_bar_network_speed_indicator, R.string.system_ui, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_network_speed_indicator_title, R.string.system_ui_statusbar_network_speed_indicator_title, R.string.system_ui_statusbar_network_speed_indicator_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar.NetworkSpeedIndicatorSettings"); parsePrefXml(context, R.xml.system_ui_status_bar_clock_indicator, R.string.system_ui, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_clock_title, R.string.system_ui_statusbar_clock_title, R.string.system_ui_statusbar_clock_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar.ClockIndicatorSettings"); parsePrefXml(context, R.xml.system_ui_status_bar_hardware_detail_indicator, R.string.system_ui, R.string.system_ui_statusbar_title, R.string.system_ui_statusbar_device_title, R.string.system_ui_statusbar_device_title, R.string.system_ui_statusbar_device_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.statusbar.BatteryDetailIndicatorSettings"); parsePrefXml(context, R.xml.system_ui_navigation, R.string.system_ui, R.string.system_ui_navigation_title, R.string.system_ui_navigation_title, R.string.system_ui_navigation_title, R.string.system_ui_navigation_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.NavigationSettings"); parsePrefXml(context, R.xml.system_ui_control_center, R.string.system_ui, R.string.system_ui_controlcenter_title, R.string.system_ui_controlcenter_title, R.string.system_ui_controlcenter_title, R.string.system_ui_controlcenter_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.ControlCenterSettings"); parsePrefXml(context, R.xml.system_ui_other, R.string.system_ui, R.string.system_ui_other_title, R.string.system_ui_other_title, R.string.system_ui_other_title, R.string.system_ui_other_title, "com.sevtinge.cemiuiler.ui.fragment.systemui.SystemUIOtherSettings"); // 系统桌面相关 parsePrefXml(context, R.xml.home_gesture, R.string.home, R.string.home_gesture, R.string.home_gesture, R.string.home_gesture, R.string.home_gesture, "com.sevtinge.cemiuiler.ui.fragment.home.HomeGestureSettings"); parsePrefXml(context, R.xml.home_layout, R.string.home, R.string.home_layout, R.string.home_layout, R.string.home_layout, R.string.home_layout, "com.sevtinge.cemiuiler.ui.fragment.home.HomeLayoutSettings"); parsePrefXml(context, R.xml.home_folder, R.string.home, R.string.home_folder, R.string.home_folder, R.string.home_folder, R.string.home_folder, "com.sevtinge.cemiuiler.ui.fragment.home.HomeFolderSettings"); parsePrefXml(context, R.xml.home_drawer, R.string.home, R.string.home_drawer, R.string.home_drawer, R.string.home_drawer, R.string.home_drawer, "com.sevtinge.cemiuiler.ui.fragment.home.HomeDrawerSettings"); parsePrefXml(context, R.xml.home_title, R.string.home, R.string.home_title, R.string.home_title, R.string.home_title, R.string.home_title, "com.sevtinge.cemiuiler.ui.fragment.home.HomeTitleSettings"); parsePrefXml(context, R.xml.home_title_anim, R.string.home, R.string.home_title, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param, "com.sevtinge.cemiuiler.ui.fragment.home.HomeTitleAnimSettings"); parsePrefXml(context, R.xml.home_title_anim_1, R.string.home, R.string.home_title, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param_1_title, R.string.home_title_custom_anim_param_1_title, "com.sevtinge.cemiuiler.ui.fragment.home.anim.HomeTitleAnim1Settings"); parsePrefXml(context, R.xml.home_title_anim_2, R.string.home, R.string.home_title, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param_2_title, R.string.home_title_custom_anim_param_2_title, "com.sevtinge.cemiuiler.ui.fragment.home.anim.HomeTitleAnim2Settings"); parsePrefXml(context, R.xml.home_title_anim_3, R.string.home, R.string.home_title, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param_3_title, R.string.home_title_custom_anim_param_3_title, "com.sevtinge.cemiuiler.ui.fragment.home.anim.HomeTitleAnim3Settings"); parsePrefXml(context, R.xml.home_title_anim_4, R.string.home, R.string.home_title, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param_4_title, R.string.home_title_custom_anim_param_4_title, "com.sevtinge.cemiuiler.ui.fragment.home.anim.HomeTitleAnim4Settings"); parsePrefXml(context, R.xml.home_title_anim_5, R.string.home, R.string.home_title, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param_5_title, R.string.home_title_custom_anim_param_5_title, "com.sevtinge.cemiuiler.ui.fragment.home.anim.HomeTitleAnim5Settings"); parsePrefXml(context, R.xml.home_title_anim_6, R.string.home, R.string.home_title, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param_6_title, R.string.home_title_custom_anim_param_6_title, "com.sevtinge.cemiuiler.ui.fragment.home.anim.HomeTitleAnimSettings"); parsePrefXml(context, R.xml.home_title_anim_7, R.string.home, R.string.home_title, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param_7_title, R.string.home_title_custom_anim_param_7_title, "com.sevtinge.cemiuiler.ui.fragment.home.anim.HomeTitleAnim7Settings"); parsePrefXml(context, R.xml.home_title_anim_8, R.string.home, R.string.home_title, R.string.home_title_custom_anim_param, R.string.home_title_custom_anim_param_8_title, R.string.home_title_custom_anim_param_8_title, "com.sevtinge.cemiuiler.ui.fragment.home.anim.HomeTitleAnim8Settings"); parsePrefXml(context, R.xml.home_recent, R.string.home, R.string.home_recent, R.string.home_recent, R.string.home_recent, R.string.home_recent, "com.sevtinge.cemiuiler.ui.fragment.home.HomeRecentSettings"); parsePrefXml(context, R.xml.home_widget, R.string.home, R.string.home_widget, R.string.home_widget, R.string.home_widget, R.string.home_widget, "com.sevtinge.cemiuiler.ui.fragment.home.HomeWidgetSettings"); parsePrefXml(context, R.xml.home_dock, R.string.home, R.string.home_dock, R.string.home_dock, R.string.home_dock, R.string.home_dock, "com.sevtinge.cemiuiler.ui.fragment.home.HomeDockSettings"); parsePrefXml(context, R.xml.home_other, R.string.home, R.string.home_other, R.string.home_other, R.string.home_other, R.string.home_other, "com.sevtinge.cemiuiler.ui.fragment.home.HomeOtherSettings"); // 设置相关 parsePrefXml(context, R.xml.system_settings, R.string.system_settings, R.string.system_settings, R.string.system_settings, R.string.system_settings, R.string.system_settings, "com.sevtinge.cemiuiler.ui.fragment.SystemSettingsFragment"); // 其他杂项 parsePrefXml(context, R.xml.browser, R.string.browser, R.string.browser, R.string.browser, R.string.browser, R.string.browser, "com.sevtinge.cemiuiler.ui.fragment.BrowserFragment"); parsePrefXml(context, R.xml.camera, R.string.camera, R.string.camera, R.string.camera, R.string.camera, R.string.camera, "com.sevtinge.cemiuiler.ui.fragment.CameraFragment"); parsePrefXml(context, R.xml.clock, R.string.clock, R.string.clock, R.string.clock, R.string.clock, R.string.clock, "com.sevtinge.cemiuiler.ui.fragment.ClockFragment"); parsePrefXml(context, R.xml.fileexplorer, R.string.fileexplorer, R.string.fileexplorer, R.string.fileexplorer, R.string.fileexplorer, R.string.fileexplorer, "com.sevtinge.cemiuiler.ui.fragment.FileExplorerFragment"); parsePrefXml(context, R.xml.incallui, R.string.incallui, R.string.incallui, R.string.incallui, R.string.incallui, R.string.incallui, "com.sevtinge.cemiuiler.ui.fragment.InCallUiFragment"); parsePrefXml(context, R.xml.mms, R.string.mms, R.string.mms, R.string.mms, R.string.mms, R.string.mms, "com.sevtinge.cemiuiler.ui.fragment.MmsFragment"); parsePrefXml(context, R.xml.nfc, R.string.nfc, R.string.nfc, R.string.nfc, R.string.nfc, R.string.nfc, "com.sevtinge.cemiuiler.ui.fragment.NfcFragment"); parsePrefXml(context, R.xml.phone, R.string.phone, R.string.phone, R.string.phone, R.string.phone, R.string.phone, "com.sevtinge.cemiuiler.ui.fragment.PhoneFragment"); parsePrefXml(context, R.xml.downloads, R.string.downloads, R.string.downloads, R.string.downloads, R.string.downloads, R.string.downloads, "com.sevtinge.cemiuiler.ui.fragment.DownloadsFragment"); parsePrefXml(context, R.xml.updater, R.string.updater, R.string.updater, R.string.updater, R.string.updater, R.string.updater, "com.sevtinge.cemiuiler.ui.fragment.UpdaterFragment"); parsePrefXml(context, R.xml.lbe_security, R.string.lbe, R.string.lbe, R.string.lbe, R.string.lbe, R.string.lbe, "com.sevtinge.cemiuiler.ui.fragment.LbeFragment"); parsePrefXml(context, R.xml.milink, R.string.milink, R.string.milink, R.string.milink, R.string.milink, R.string.milink, "com.sevtinge.cemiuiler.ui.fragment.MiLinkFragment"); parsePrefXml(context, R.xml.aod, R.string.aod, R.string.aod, R.string.aod, R.string.aod, R.string.aod, "com.sevtinge.cemiuiler.ui.fragment.AodFragment"); parsePrefXml(context, R.xml.content_extension, R.string.content_extension, R.string.content_extension, R.string.content_extension, R.string.content_extension, R.string.content_extension, "com.sevtinge.cemiuiler.ui.fragment.ContentExtensionFragment"); parsePrefXml(context, R.xml.gallery, R.string.gallery, R.string.gallery, R.string.gallery, R.string.gallery, R.string.gallery, "com.sevtinge.cemiuiler.ui.fragment.GalleryFragment"); parsePrefXml(context, R.xml.guard_provider, R.string.guard_provider, R.string.guard_provider, R.string.guard_provider, R.string.guard_provider, R.string.guard_provider, "com.sevtinge.cemiuiler.ui.fragment.GuardProviderFragment"); parsePrefXml(context, R.xml.mediaeditor, R.string.mediaeditor, R.string.mediaeditor, R.string.mediaeditor, R.string.mediaeditor, R.string.mediaeditor, "com.sevtinge.cemiuiler.ui.fragment.MediaEditorFragment"); parsePrefXml(context, R.xml.mishare, R.string.mishare, R.string.mishare, R.string.mishare, R.string.mishare, R.string.mishare, "com.sevtinge.cemiuiler.ui.fragment.MiShareFragment"); parsePrefXml(context, R.xml.miwallpaper, R.string.miwallpaper, R.string.miwallpaper, R.string.miwallpaper, R.string.miwallpaper, R.string.miwallpaper, "com.sevtinge.cemiuiler.ui.fragment.MiWallpaperFragment"); parsePrefXml(context, R.xml.package_installer, R.string.package_installer, R.string.package_installer, R.string.package_installer, R.string.package_installer, R.string.package_installer, "com.sevtinge.cemiuiler.ui.fragment.MiuiPackageInstallerFragment"); parsePrefXml(context, R.xml.music, R.string.music, R.string.music, R.string.music, R.string.music, R.string.music, "com.sevtinge.cemiuiler.ui.fragment.MusicFragment"); parsePrefXml(context, R.xml.powerkeeper, R.string.powerkeeper, R.string.powerkeeper, R.string.powerkeeper, R.string.powerkeeper, R.string.powerkeeper, "com.sevtinge.cemiuiler.ui.fragment.PowerKeeperFragment"); parsePrefXml(context, R.xml.screenrecorder, R.string.screenrecorder, R.string.screenrecorder, R.string.screenrecorder, R.string.screenrecorder, R.string.screenrecorder, "com.sevtinge.cemiuiler.ui.fragment.ScreenRecorderFragment"); parsePrefXml(context, R.xml.screenshot, R.string.screenshot, R.string.screenshot, R.string.screenshot, R.string.screenshot, R.string.screenshot, "com.sevtinge.cemiuiler.ui.fragment.ScreenShotFragment"); parsePrefXml(context, R.xml.security_center, !isPad() ? R.string.security_center : R.string.security_center_pad, !isPad() ? R.string.security_center : R.string.security_center_pad, !isPad() ? R.string.security_center : R.string.security_center_pad, !isPad() ? R.string.security_center : R.string.security_center_pad, !isPad() ? R.string.security_center : R.string.security_center_pad, "com.sevtinge.cemiuiler.ui.fragment.SecurityCenterFragment"); parsePrefXml(context, R.xml.tsmclient, R.string.tsmclient, R.string.tsmclient, R.string.tsmclient, R.string.tsmclient, R.string.tsmclient, "com.sevtinge.cemiuiler.ui.fragment.TsmClientFragment"); parsePrefXml(context, R.xml.weather, R.string.weather, R.string.weather, R.string.weather, R.string.weather, R.string.weather, "com.sevtinge.cemiuiler.ui.fragment.WeatherFragment"); parsePrefXml(context, R.xml.aiasst, R.string.aiasst, R.string.aiasst, R.string.aiasst, R.string.aiasst, R.string.aiasst, "com.sevtinge.cemiuiler.ui.fragment.AiAsstFragment"); parsePrefXml(context, R.xml.tsmclient, R.string.tsmclient, R.string.tsmclient, R.string.tsmclient, R.string.tsmclient, R.string.tsmclient, "com.sevtinge.cemiuiler.ui.fragment.TsmClientFragment"); parsePrefXml(context, R.xml.barrage, R.string.barrage, R.string.barrage, R.string.barrage, R.string.barrage, R.string.barrage, "com.sevtinge.cemiuiler.ui.fragment.BarrageFragment"); parsePrefXml(context, R.xml.joyose, R.string.joyose, R.string.joyose, R.string.joyose, R.string.joyose, R.string.joyose, "com.sevtinge.cemiuiler.ui.fragment.JoyoseFragment"); parsePrefXml(context, R.xml.market, R.string.market, R.string.market, R.string.market, R.string.market, R.string.market, "com.sevtinge.cemiuiler.ui.fragment.MarketFragment"); parsePrefXml(context, R.xml.mirror, R.string.mirror, R.string.mirror, R.string.mirror, R.string.mirror, R.string.mirror, "com.sevtinge.cemiuiler.ui.fragment.MirrorFragment"); parsePrefXml(context, R.xml.mtb, R.string.mtb, R.string.mtb, R.string.mtb, R.string.mtb, R.string.mtb, "com.sevtinge.cemiuiler.ui.fragment.MtbFragment"); parsePrefXml(context, R.xml.scanner, R.string.scanner, R.string.scanner, R.string.scanner, R.string.scanner, R.string.scanner, "com.sevtinge.cemiuiler.ui.fragment.ScannerFragment"); parsePrefXml(context, R.xml.creation, R.string.creation, R.string.creation, R.string.creation, R.string.creation, R.string.creation, "com.sevtinge.cemiuiler.ui.fragment.CreationFragment"); parsePrefXml(context, R.xml.various, R.string.various, R.string.various, R.string.various, R.string.various, R.string.various, "com.sevtinge.cemiuiler.ui.fragment.VariousFragment"); parsePrefXml(context, R.xml.various_aosp, R.string.various, R.string.various, R.string.various_open_aosp_something_title, R.string.various_open_aosp_something_title, R.string.various_open_aosp_something_title, "com.sevtinge.cemiuiler.ui.fragment.various.AOSPSettings"); if (isPad()) { parsePrefXml(context, R.xml.various_mipad, R.string.various, R.string.various_mipad_title, R.string.various_mipad_title, R.string.various_mipad_title, R.string.various_mipad_title, "com.sevtinge.cemiuiler.ui.fragment.VariousFragment"); } // 实验性 parsePrefXml(context, R.xml.theme_manager, R.string.theme_manager, R.string.theme_manager, R.string.theme_manager, R.string.theme_manager, R.string.theme_manager, "com.sevtinge.cemiuiler.ui.fragment.ThemeManagerFragment"); parsePrefXml(context, R.xml.personal_assistant, R.string.personal_assistant, R.string.personal_assistant, R.string.personal_assistant, R.string.personal_assistant, R.string.personal_assistant, "com.sevtinge.cemiuiler.ui.fragment.PersonalAssistantFragment"); } private static void parsePrefXml(Context context, int xmlResId, int catResId, int catSub1ResId, int catSub2ResId, int catSub3ResId, int catSub4ResId, String catPrefsFragment) { Resources res = context.getResources(); try (XmlResourceParser xml = res.getXml(xmlResId)) { int order = 0; int eventType = xml.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG && !xml.getName().equals("PreferenceCategory")) { try { ModData modData = new ModData(); modData.title = getModTitle(res, xml.getAttributeValue(ANDROID_NS, "title")); if (Objects.equals(modData.title, res.getString(R.string.theme_manager_crack)) || Objects.equals(modData.title, res.getString(R.string.personal_assistant_widget_crack))) modData.title = ""; if (!TextUtils.isEmpty(modData.title)) { if (!res.getString(catSub3ResId).equals(res.getString(catSub4ResId))) { modData.breadcrumbs = res.getString(catResId) + "/" + res.getString(catSub1ResId) + "/" + res.getString(catSub2ResId) + "/" + res.getString(catSub3ResId) + "/" + res.getString(catSub4ResId); } else if (!res.getString(catSub2ResId).equals(res.getString(catSub3ResId))) { modData.breadcrumbs = res.getString(catResId) + "/" + res.getString(catSub1ResId) + "/" + res.getString(catSub2ResId) + "/" + res.getString(catSub3ResId); } else if (!res.getString(catSub1ResId).equals(res.getString(catSub2ResId))) { modData.breadcrumbs = res.getString(catResId) + "/" + res.getString(catSub1ResId) + "/" + res.getString(catSub2ResId); } else if (!res.getString(catResId).equals(res.getString(catSub1ResId))) { modData.breadcrumbs = res.getString(catResId) + "/" + res.getString(catSub1ResId); } else { modData.breadcrumbs = res.getString(catResId); } modData.key = xml.getAttributeValue(ANDROID_NS, "key"); modData.order = order; modData.catTitleResId = catSub4ResId; modData.fragment = catPrefsFragment; allModsList.add(modData); } order++; } catch (Throwable t) { t.printStackTrace(); } } eventType = xml.next(); } } catch (Throwable t) { t.printStackTrace(); } } private static String getModTitle(Resources res, String title) { if (title == null) { return null; } int titleResId = Integer.parseInt(title.substring(1)); if (titleResId <= 0) { return null; } return res.getString(titleResId); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/SettingLauncher.java ================================================ package com.sevtinge.cemiuiler.utils; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import androidx.fragment.app.Fragment; public class SettingLauncher { private final Context mContext; private boolean mLaunched; Bundle mExtras; Bundle mArguments; CharSequence mTitle; String mDestinationName; Class mClass; int mTitleResId; public SettingLauncher(Context context) { if (context == null) { throw new IllegalArgumentException("Context must be non-null."); } mContext = context; } public SettingLauncher setClass(Class cls) { mClass = cls; return this; } public SettingLauncher setDestination(String name) { mDestinationName = name; return this; } public SettingLauncher setTitleRes(int titleResId) { mTitleResId = titleResId; return this; } public SettingLauncher setTitleText(CharSequence title) { mTitle = title; return this; } public SettingLauncher setArguments(Bundle args) { mArguments = args; return this; } public SettingLauncher setExtras(Bundle extras) { mExtras = extras; return this; } public void launch() { if (mLaunched) { throw new IllegalStateException("This launcher has already been executed. Do not reuse"); } mLaunched = true; Intent intent = toIntent(); launch(intent); } public Intent toIntent() { Intent intent = new Intent("android.intent.action.MAIN"); copyExtras(intent); intent.setClass(mContext, mClass); if (TextUtils.isEmpty(mDestinationName)) { throw new IllegalArgumentException("Destination fragment must be set"); } intent.putExtra(":settings:show_fragment", mDestinationName); intent.putExtra(":settings:show_fragment_args", mArguments); intent.putExtra(":settings:show_fragment_title", mTitle); intent.putExtra(":settings:show_fragment_title_resid", mTitleResId); /*intent.putExtra(":settings:show_fragment_contentResId", mContentResId);*/ return intent; } void launch(Intent intent) { mContext.startActivity(intent); } void launchForResult(Fragment fragment, Intent intent, int i) { fragment.startActivityForResult(intent, i); } private void copyExtras(Intent intent) { if (mExtras != null) { intent.replaceExtras(mExtras); } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/SettingLauncherHelper.java ================================================ package com.sevtinge.cemiuiler.utils; import android.content.Context; import android.os.Bundle; public class SettingLauncherHelper { public static void onStartSettingsForArguments(Context context, Class cls, String fragment, String title) { onStartSettingsForArguments(context, cls, fragment, null, title); } public static void onStartSettingsForArguments(Context context, Class cls, String fragment, int titleResId) { onStartSettingsForArguments(context, cls, fragment, null, titleResId); } public static void onStartSettingsForArguments(Context context, Class cls, String fragment, Bundle args, String title) { onStartSettingsForArguments(context, cls, fragment, args, 0, title); } public static void onStartSettingsForArguments(Context context, Class cls, String fragment, Bundle args, int titleResId) { onStartSettingsForArguments(context, cls, fragment, args, titleResId, null); } public static void onStartSettingsForArguments(Context context, Class cls, String fragment, Bundle args, int titleResId, String title) { if (args == null) args = new Bundle(); onStartSettings(context, cls, fragment, null, args, titleResId, title); } public static void onStartSettingsForExtras(Context context, Class cls, String fragment, Bundle extras, int titleResId, String title) { if (extras == null) extras = new Bundle(); onStartSettings(context, cls, fragment, extras, null, titleResId, title); } public static void onStartSettings(Context context, Class cls, Class fname, String title) { onStartSettings(context, cls, fname, null, null, 0, title); } public static void onStartSettings(Context context, Class cls, Class fname, Bundle extras, Bundle args, String title) { onStartSettings(context, cls, fname, extras, args, 0, title); } public static void onStartSettings(Context context, Class cls, Class fname, Bundle extras, Bundle args, int titleResId, String title) { if (args == null) args = new Bundle(); onStartSettings(context, cls, fname.getName(), extras, args, titleResId, title); } public static void onStartSettings(Context context, Class cls, String fragment, Bundle extras, Bundle args, int titleResId, String title) { new SettingLauncher(context) .setClass(cls) .setDestination(fragment) .setTitleText(title) .setTitleRes(titleResId) .setExtras(extras) .setArguments(args) .launch(); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/ShakeManager.java ================================================ package com.sevtinge.cemiuiler.utils; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import com.sevtinge.cemiuiler.module.app.GlobalActions; public class ShakeManager implements SensorEventListener { private float xAccel; private float yAccel; private float zAccel; private float xPreviousAccel; private float yPreviousAccel; private float zPreviousAccel; private boolean firstUpdate = true; private boolean shakeInitiated = false; private long lastShakeEvent = System.currentTimeMillis(); private final Context helperContext; public ShakeManager(Context helpercontext) { this.helperContext = helpercontext; } public void reset() { xAccel = 0; yAccel = 0; zAccel = 0; xPreviousAccel = 0; yPreviousAccel = 0; zPreviousAccel = 0; firstUpdate = true; shakeInitiated = false; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // Don't care... } @Override public void onSensorChanged(SensorEvent se) { updateAccelParameters(se.values[0], se.values[1], se.values[2]); if (!shakeInitiated && isAccelerationChanged()) shakeInitiated = true; else if (shakeInitiated && isAccelerationChanged()) executeShakeActionDelayed(); else if (shakeInitiated && (!isAccelerationChanged())) shakeInitiated = false; } private void updateAccelParameters(float xNewAccel, float yNewAccel, float zNewAccel) { if (firstUpdate) { xPreviousAccel = xNewAccel; yPreviousAccel = yNewAccel; zPreviousAccel = zNewAccel; firstUpdate = false; } else { xPreviousAccel = xAccel; yPreviousAccel = yAccel; zPreviousAccel = zAccel; } xAccel = xNewAccel; yAccel = yNewAccel; zAccel = zNewAccel; } private boolean isAccelerationChanged() { float deltaX = Math.abs(xPreviousAccel - xAccel); float deltaY = Math.abs(yPreviousAccel - yAccel); float deltaZ = Math.abs(zPreviousAccel - zAccel); float shakeThresholdX = 4f; float shakeThresholdY = 4f; float shakeThresholdZ = 8f; return (deltaX > shakeThresholdX && deltaY > shakeThresholdY) || (deltaX > shakeThresholdX && deltaZ > shakeThresholdZ) || (deltaY > shakeThresholdY && deltaZ > shakeThresholdZ); } private void executeShakeActionDelayed() { long now = System.currentTimeMillis(); int shakeEventThrottle = 750; if (now - lastShakeEvent > shakeEventThrottle) { lastShakeEvent = now; executeShakeAction(); } } private void executeShakeAction() { GlobalActions.handleAction(helperContext, "prefs_key_home_gesture_shake"); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/ShellUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import com.sevtinge.cemiuiler.utils.log.AndroidLogUtils; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.List; public class ShellUtils { /** * check whether has root permission * * @return if int = 0, then have root, else don't have. */ public static int checkRootPermission() { Process process = null; int exitCode = -1; try { process = Runtime.getRuntime().exec("su -c true"); return process.waitFor(); } catch (IOException | InterruptedException e) { AndroidLogUtils.LogE("checkRootPermission", "check whether has root permission error: ", e); return exitCode; } finally { if (process != null) { process.destroy(); } } } /** * execute shell command, default return result msg * * @param command command * @param isRoot whether need to run with root * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String command, boolean isRoot) { return execCommand(new String[]{command}, isRoot, true); } /** * execute shell commands, default return result msg * * @param commands command activity_wifi * @param isRoot whether need to run with root * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(List commands, boolean isRoot) { return execCommand(commands == null ? null : commands.toArray(new String[]{}), isRoot, true); } /** * execute shell commands, default return result msg * * @param commands command array * @param isRoot whether need to run with root * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String[] commands, boolean isRoot) { return execCommand(commands, isRoot, true); } /** * execute shell command * * @param command command * @param isRoot whether need to run with root * @param isNeedResultMsg whether need result msg * @noinspection UnusedReturnValue * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(String command, boolean isRoot, boolean isNeedResultMsg) { return execCommand(new String[]{command}, isRoot, isNeedResultMsg); } /** * execute shell commands * * @param commands command activity_wifi * @param isRoot whether need to run with root * @param isNeedResultMsg whether need result msg * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static CommandResult execCommand(List commands, boolean isRoot, boolean isNeedResultMsg) { return execCommand(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg); } /** * execute shell commands * * @param command command activity_wifi * @param isRoot whether need to run with root * @return if execCommand.result is 0, then return true, else return false * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static boolean getResultBoolean(String command, boolean isRoot) { return execCommand(new String[]{command}, isRoot, false).result == 0; } /** * execute shell commands * * @param commands command activity_wifi * @param isRoot whether need to run with root * @return if execCommand.result is 0, then return true, else return false * @see ShellUtils#execCommand(String[], boolean, boolean) */ public static boolean getResultBoolean(List commands, boolean isRoot) { return execCommand(commands == null ? null : commands.toArray(new String[]{}), isRoot, false).result == 0; } /** * execute shell commands * * @param commands command array * @param isRoot whether need to run with root * @param isNeedResultMsg whether need result msg * @return

    *
  • if isNeedResultMsg is false, {@link CommandResult#successMsg} is null and * {@link CommandResult#errorMsg} is null.
  • *
  • if {@link CommandResult#result} is -1, there maybe some excepiton.
  • *
*/ public static CommandResult execCommand(String[] commands, boolean isRoot, boolean isNeedResultMsg) { int result = -1; if (commands == null || commands.length == 0) { return new CommandResult(result, null, null); } Process process = null; BufferedReader successResult = null; BufferedReader errorResult = null; StringBuilder successMsg = null; StringBuilder errorMsg = null; DataOutputStream os = null; try { // if (isRoot) { // int exitCode = checkRootPermission(); // if (exitCode != 0) { // return new CommandResult(exitCode, null, null); // } // } process = Runtime.getRuntime().exec(isRoot ? "su" : "sh"); os = new DataOutputStream(process.getOutputStream()); for (String command : commands) { if (command == null) { continue; } // donnot use os.writeBytes(commmand), avoid chinese charset error os.write(command.getBytes()); // os.writeBytes(command); os.writeBytes("\n"); os.flush(); } os.writeBytes("exit\n"); os.flush(); result = process.waitFor(); // get command result if (isNeedResultMsg) { successMsg = new StringBuilder(); errorMsg = new StringBuilder(); successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); String s; while ((s = successResult.readLine()) != null) { successMsg.append(s); } while ((s = errorResult.readLine()) != null) { errorMsg.append(s); } } } catch (IOException | InterruptedException e) { AndroidLogUtils.LogE("execCommand", "IOException | InterruptedException: ", e); } finally { try { if (os != null) { os.close(); } if (successResult != null) { successResult.close(); } if (errorResult != null) { errorResult.close(); } } catch (IOException e) { e.printStackTrace(); } if (process != null) { process.destroy(); } } return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null : errorMsg.toString()); } /** * result of command *
    *
  • {@link CommandResult#result} means result of command, 0 means normal, else means error, same to excute in * linux shell
  • *
  • {@link CommandResult#successMsg} means success message of command result
  • *
  • {@link CommandResult#errorMsg} means error message of command result
  • *
* * @author
Trinea
2013-5-16 */ public static class CommandResult { /** * result of command **/ public int result; /** * success message of command result **/ public String successMsg; /** * error message of command result **/ public String errorMsg; public CommandResult(int result) { this.result = result; } public CommandResult(int result, String successMsg, String errorMsg) { this.result = result; this.successMsg = successMsg; this.errorMsg = errorMsg; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/SystemProperties.kt ================================================ package com.sevtinge.cemiuiler.utils import android.annotation.SuppressLint import android.content.Context object SystemProperties { @SuppressLint("PrivateApi") operator fun get(context: Context, key: String?): String { var ret: String try { val cl = context.classLoader val systemProperties = cl.loadClass("android.os.SystemProperties") // 参数类型 val paramTypes: Array?> = arrayOfNulls(1) paramTypes[0] = String::class.java val get = systemProperties.getMethod("get", *paramTypes) // 参数 val params = arrayOfNulls(1) params[0] = key ret = get.invoke(systemProperties, *params) as String } catch (iAE: IllegalArgumentException) { throw iAE } catch (e: Exception) { ret = "" } return ret } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/TileUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.os.Build; import android.util.ArrayMap; import android.view.View; import android.widget.Switch; import com.sevtinge.cemiuiler.module.base.BaseHook; import com.sevtinge.cemiuiler.utils.log.XposedLogUtils; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.XposedHelpers; public abstract class TileUtils extends BaseHook { Class mResourceIcon; Class mQSFactory; final boolean[] isListened = {false}; /*固定语法,必须调用。 * 调用方法: * @Override * public void init() { * super.init(); * } * */ @Override public void init() { mQSFactory = customQSFactory(); Class myTile = customClass(); mResourceIcon = findClass("com.android.systemui.qs.tileimpl.QSTileImpl$ResourceIcon"); SystemUiHook(); // 不需要覆写 tileAllName(mQSFactory); // 不需要覆写 showStateMessage(myTile); if (Build.VERSION.SDK_INT == Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { tileAllName14(mQSFactory); } try { myTile.getDeclaredMethod("isAvailable"); findAndHookMethod(myTile, "isAvailable", new MethodHook() { @Override protected void before(MethodHookParam param) { String tileName = (String) XposedHelpers.getAdditionalInstanceField(param.thisObject, "customName"); if (tileName != null) { if (tileName.equals(customName())) { tileCheck(param, tileName); } } else { if (!needCustom()) tileCheck(param, tileName); } } }); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have isAvailable: " + e); } tileName(myTile); // 不需要覆写 try { myTile.getDeclaredMethod("handleSetListening", boolean.class); findAndHookMethod(myTile, "handleSetListening", boolean.class, new MethodHook() { @Override protected void before(MethodHookParam param) { String tileName = (String) XposedHelpers.getAdditionalInstanceField(param.thisObject, "customName"); if (tileName != null) { if (tileName.equals(customName())) { try { tileListening(param, tileName); param.setResult(null); } catch (Throwable e) { XposedLogUtils.logE(TAG, "handleSetListening have Throwable: " + e); param.setResult(null); } } } else { if (!needCustom()) tileListening(param, tileName); } } }); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have handleSetListening: " + e); } try { myTile.getDeclaredMethod("getLongClickIntent"); findAndHookMethod(myTile, "getLongClickIntent", new MethodHook() { @Override protected void before(MethodHookParam param) { String tileName = (String) XposedHelpers.getAdditionalInstanceField(param.thisObject, "customName"); if (tileName != null) { if (tileName.equals(customName())) { tileLongClickIntent(param, tileName); } } else { if (!needCustom()) tileLongClickIntent(param, tileName); } } }); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have getLongClickIntent: " + e); } try { myTile.getDeclaredMethod("handleLongClick", View.class); findAndHookMethod(myTile, "handleLongClick", View.class, new MethodHook() { @Override protected void before(MethodHookParam param) { String tileName = (String) XposedHelpers.getAdditionalInstanceField(param.thisObject, "customName"); if (tileName != null && needCustom()) { if (tileName.equals(customName())) { Intent intent = tileHandleLongClick(param, tileName); if (intent != null) { Context context = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); Object o = XposedHelpers.callStaticMethod(findClassIfExists("com.android.systemui.controlcenter.utils.ControlCenterUtils"), "getSettingsSplitIntent", context, intent); XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "mActivityStarter"), "postStartActivityDismissingKeyguard", o, 0, null); param.setResult(null); } } } } }); } catch (NoSuchMethodException t) { XposedLogUtils.logE(TAG, "Don't Have handleLongClick: " + t); } try { myTile.getDeclaredMethod("handleClick", View.class); findAndHookMethod(myTile, "handleClick", View.class, new MethodHook() { @Override protected void before(MethodHookParam param) { String tileName = (String) XposedHelpers.getAdditionalInstanceField(param.thisObject, "customName"); if (tileName != null) { if (tileName.equals(customName())) { try { tileClick(param, tileName); param.setResult(null); } catch (Throwable e) { XposedLogUtils.logE(TAG, "handleClick have Throwable: " + e); param.setResult(null); } } } else { if (!needCustom()) tileClick(param, tileName); } } @Override protected void after(MethodHookParam param) { if (needAfter()) { String tileName = (String) XposedHelpers.getAdditionalInstanceField(param.thisObject, "customName"); tileClickAfter(param, tileName); } } }); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have handleClick: " + e); } hookAllMethods(myTile, "handleUpdateState", new MethodHook() { @Override protected void before(MethodHookParam param) { String tileName = (String) XposedHelpers.getAdditionalInstanceField(param.thisObject, "customName"); if (tileName != null) { if (tileName.equals(customName())) { boolean isEnable = false; ArrayMap tileResMap; tileResMap = tileUpdateState(param, mResourceIcon, tileName); if (tileResMap != null) { int code = tileResMap.get(customName() + "_Enable"); if (code == 1) isEnable = true; Object booleanState = param.args[0]; XposedHelpers.setObjectField(booleanState, "value", isEnable); // 测试为开关状态控制,2为开,1为关 XposedHelpers.setObjectField(booleanState, "state", isEnable ? 2 : 1); String tileLabel = (String) XposedHelpers.callMethod(param.thisObject, "getTileLabel"); XposedHelpers.setObjectField(booleanState, "label", tileLabel); XposedHelpers.setObjectField(booleanState, "contentDescription", tileLabel); XposedHelpers.setObjectField(booleanState, "expandedAccessibilityClassName", Switch.class.getName()); Object mIcon = XposedHelpers.callStaticMethod(mResourceIcon, "get", isEnable ? tileResMap.get(customName() + "_ON") : tileResMap.get(customName() + "_OFF")); XposedHelpers.setObjectField(booleanState, "icon", mIcon); } param.setResult(null); } } else { if (!needCustom()) tileUpdateState(param, mResourceIcon, tileName); } } }); } /*用于指定磁贴工厂函数*/ public Class customQSFactory() { return null; } /*需要Hook的磁贴Class*/ public Class customClass() { return null; } /*需要Hook执行的Class方法*/ public String[] customTileProvider() { return null; } /*请在这里输入你需要的自定义快捷方式名称。*/ public String customName() { return ""; } /*在这里为你的自定义磁贴打上标题 需要传入资源Id*/ public int customValue() { return -1; } /*是否使用自定义的方式创建磁贴 否则为在原有磁贴逻辑上进行修改*/ public boolean needCustom() { return false; } /*是否需要在after时进行逻辑修改而不是before*/ public boolean needAfter() { return false; } /* * 在第一次Hook时把新的快捷方式加载进快捷方式列表中。 * */ private void SystemUiHook() { String custom = customName(); if (needCustom()) { if ("".equals(custom)) { XposedLogUtils.logE(TAG, "Error custom:" + custom); return; } try { findClassIfExists("com.android.systemui.SystemUIApplication").getDeclaredMethod("onCreate"); findAndHookMethod("com.android.systemui.SystemUIApplication", "onCreate", new MethodHook() { @Override protected void after(MethodHookParam param) { if (!isListened[0]) { isListened[0] = true; // 获取Context Context mContext = (Context) XposedHelpers.callMethod(param.thisObject, "getApplicationContext"); // 获取miui_quick_settings_tiles_stock字符串的值 @SuppressLint("DiscouragedApi") int stockTilesResId = mContext.getResources().getIdentifier("miui_quick_settings_tiles_stock", "string", lpparam.packageName); String stockTiles = mContext.getString(stockTilesResId) + "," + custom; // 追加自定义的磁贴 // 将拼接后的字符串分别替换下面原有的字符串。 mResHook.setObjectReplacement(lpparam.packageName, "string", "miui_quick_settings_tiles_stock", stockTiles); mResHook.setObjectReplacement("miui.systemui.plugin", "string", "miui_quick_settings_tiles_stock", stockTiles); mResHook.setObjectReplacement("miui.systemui.plugin", "string", "quick_settings_tiles_stock", stockTiles); } } }); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have onCreate: " + e); } } } /* * 判断是否是自定义磁贴,如果是则在自定义磁贴前加上Key,用于定位磁贴。 */ private void tileAllName(Class QSFactory) { if (needCustom()) { try { QSFactory.getDeclaredMethod(customTileProvider()[1], String.class); findAndHookMethod(QSFactory, customTileProvider()[1], String.class, new MethodHook() { @Override protected void before(MethodHookParam param) { String tileName = (String) param.args[0]; if (tileName.equals(customName())) { String myTileProvider = customTileProvider()[0]; Object provider = XposedHelpers.getObjectField(param.thisObject, myTileProvider); Object tile = XposedHelpers.callMethod(provider, "get"); XposedHelpers.setAdditionalInstanceField(tile, "customName", tileName); param.setResult(tile); } } }); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have " + customTileProvider()[1], e); } } } /*安卓14磁贴逻辑被修改,此是解决方法*/ private void tileAllName14(Class QSFactory) { if (needCustom()) { try { QSFactory.getDeclaredMethod(customTileProvider()[2], String.class); findAndHookMethod(QSFactory, customTileProvider()[2], String.class, new MethodHook() { @Override protected void before(MethodHookParam param) { String tileName = (String) param.args[0]; if (tileName.equals(customName())) { String myTileProvider = customTileProvider()[0]; Object provider = XposedHelpers.getObjectField(param.thisObject, myTileProvider); Object tile = XposedHelpers.callMethod(provider, "get"); XposedHelpers.setAdditionalInstanceField(tile, "customName", tileName); if (tile != null) { Object mHandler = XposedHelpers.getObjectField(tile, "mHandler"); XposedHelpers.callMethod(mHandler, "sendEmptyMessage", 12); XposedHelpers.callMethod(mHandler, "sendEmptyMessage", 11); param.setResult(tile); } } } } ); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have " + customTileProvider()[2], e); } } } /* 新版系统界面磁贴开启关闭时会显示的文字 */ private void showStateMessage(Class myTile) { try { myTile.getDeclaredMethod("handleShowStateMessage"); findAndHookMethod(myTile, "handleShowStateMessage", new MethodHook() { @Override protected void before(MethodHookParam param) { XposedHelpers.callMethod(param.thisObject, "showStateMessage", XposedHelpers.callMethod(param.thisObject, "getStateMessage")); param.setResult(null); } } ); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have handleShowStateMessage: " + e); } } /*在这里可以为你的自定义磁贴判断系统是否支持 此方法需要覆写*/ public void tileCheck(MethodHookParam param, String tileName) { } /*为磁贴打上自定义名称*/ private void tileName(Class myTile) { if (needCustom()) { int customValue = customValue(); String custom = customName(); if (customValue == -1 || "".equals(custom)) { XposedLogUtils.logE(TAG, "Error customValue:" + customValue); return; } try { myTile.getDeclaredMethod("getTileLabel"); findAndHookMethod(myTile, "getTileLabel", new MethodHook() { @Override protected void before(MethodHookParam param) throws Throwable { String tileName = (String) XposedHelpers.getAdditionalInstanceField(param.thisObject, "customName"); if (tileName != null) { if (tileName.equals(custom)) { Context mContext = (Context) XposedHelpers.getObjectField(param.thisObject, "mContext"); Resources modRes = Helpers.getModuleRes(mContext); param.setResult(modRes.getString(customValue)); } } } }); } catch (NoSuchMethodException e) { XposedLogUtils.logE(TAG, "Don't Have getTileLabel: ", e); } } } /*这个方法用于监听系统设置变化 用于实时刷新开关状态 此方法需要自行覆写*/ public void tileListening(MethodHookParam param, String tileName) { } /*这个方法用于设置长按磁贴的动作 此方法需要自行覆写*/ public void tileLongClickIntent(MethodHookParam param, String tileName) { } /*这是另一个长按动作代码 * 可能不是很严谨,仅在上面长按动作失效时使用*/ public Intent tileHandleLongClick(MethodHookParam param, String tileName) { return null; } /*这个方法用于设置单击磁贴的动作 此方法需要自行覆写*/ public void tileClick(MethodHookParam param, String tileName) { } public void tileClickAfter(MethodHookParam param, String tileName) { } /*这个方法用于设置更新磁贴状态 此方法需要自行覆写*/ public ArrayMap tileUpdateState(MethodHookParam param, Class mResourceIcon, String tileName) { return null; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/ToastHelper.java ================================================ package com.sevtinge.cemiuiler.utils; import android.content.Context; import android.widget.Toast; import androidx.annotation.StringRes; public class ToastHelper { private static Toast mToast; public static void makeText(Context context, CharSequence text) { clearToast(); mToast = Toast.makeText(context, text, Toast.LENGTH_SHORT); mToast.show(); } public static void makeText(Context context, @StringRes int resId) { clearToast(); mToast = Toast.makeText(context, resId, Toast.LENGTH_SHORT); mToast.show(); } public static void clearToast() { if (mToast != null) { mToast.cancel(); mToast = null; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/XposedUtils.java ================================================ package com.sevtinge.cemiuiler.utils; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; public class XposedUtils { @SuppressLint("StaticFieldLeak") public static Context mModuleContext = null; public static synchronized Context getModuleContext(Context context) throws Throwable { return getModuleContext(context, null); } public static synchronized Context getModuleContext(Context context, Configuration config) throws Throwable { if (mModuleContext == null) mModuleContext = context.createPackageContext(Helpers.mAppModulePkg, Context.CONTEXT_IGNORE_SECURITY).createDeviceProtectedStorageContext(); return config == null ? mModuleContext : mModuleContext.createConfigurationContext(config); } public static synchronized Resources getModuleRes(Context context) throws Throwable { Configuration config = context.getResources().getConfiguration(); Context moduleContext = getModuleContext(context); return (config == null ? moduleContext.getResources() : moduleContext.createConfigurationContext(config).getResources()); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/api/LinQiqiApis.kt ================================================ package com.sevtinge.cemiuiler.utils.api import android.app.admin.DevicePolicyManager import android.content.Context import com.github.kyuubiran.ezxhelper.MemberExtensions.isStatic import java.lang.reflect.Method /** * 源自 EzXHelper 1.x 版本所附赠的扩展函数,2.0 丢失,暂时先复用 * * 判断类是否相同(用于判断参数) * eg: fun foo(a: Boolean, b: Int) { } * foo.parameterTypes.sameAs(*array) * foo.parameterTypes.sameAs(Boolean::class.java, Int::class.java) * foo.parameterTypes.sameAs("boolean", "int") * foo.parameterTypes.sameAs(Boolean::class.java, "int") * * @param other 其他类(支持String或者Class<*>) * @return 是否相等 */ fun Array>.sameAs(vararg other: Any): Boolean { if (this.size != other.size) return false for (i in this.indices) { when (val otherClazz = other[i]) { is Class<*> -> { if (this[i] != otherClazz) return false } is String -> { if (this[i].name != otherClazz) return false } else -> { throw IllegalArgumentException("Only support Class<*> or String") } } } return true } /** * 源自 EzXHelper 1.x 版本所附赠的扩展函数,2.0 丢失,暂时先复用 * * 扩展函数 通过类或者对象获取单个方法 * @param methodName 方法名 * @param isStatic 是否为静态方法 * @param returnType 方法返回值 填入null为无视返回值 * @param argTypes 方法参数类型 * @return 符合条件的方法 * @throws IllegalArgumentException 方法名为空 * @throws NoSuchMethodException 未找到方法 */ fun Any.method( methodName: String, returnType: Class<*>? = null, isStatic: Boolean = false, argTypes: ArgTypes = argTypes() ): Method { if (methodName.isBlank()) throw IllegalArgumentException("Method name must not be empty!") var c = if (this is Class<*>) this else this.javaClass do { c.declaredMethods.toList().asSequence() .filter { it.name == methodName } .filter { it.parameterTypes.size == argTypes.argTypes.size } .apply { if (returnType != null) filter { returnType == it.returnType } } .filter { it.parameterTypes.sameAs(*argTypes.argTypes) } .filter { it.isStatic == isStatic } .firstOrNull()?.let { it.isAccessible = true; return it } } while (c.superclass?.also { c = it } != null) throw NoSuchMethodException("Name:$methodName, Static: $isStatic, ArgTypes:${argTypes.argTypes.joinToString(",")}") } /** * 源自 EzXHelper 1.x 版本所附赠的扩展函数,2.0 丢失,暂时先复用 * 扩展函数 调用对象的方法 * * @param methodName 方法名 * @param args 形参表 可空 * @param argTypes 形参类型 可空 * @param returnType 返回值类型 为null时无视返回值类型 * @return 函数调用后的返回值 * @throws IllegalArgumentException 当方法名为空时 * @throws IllegalArgumentException 当args的长度与argTypes的长度不符时 * @throws IllegalArgumentException 当对象是一个Class时 */ fun Any.invokeMethod( methodName: String, args: Args = args(), argTypes: ArgTypes = argTypes(), returnType: Class<*>? = null ): Any? { if (methodName.isBlank()) throw IllegalArgumentException("Object name must not be empty!") if (args.args.size != argTypes.argTypes.size) throw IllegalArgumentException("Method args size must equals argTypes size!") return if (args.args.isEmpty()) { try { this.method(methodName, returnType, false) } catch (e: NoSuchMethodException) { return null }.invoke(this) } else { try { this.method(methodName, returnType, false, argTypes = argTypes) } catch (e: NoSuchMethodException) { return null }.invoke(this, *args.args) } } /** * 检测设备是否加密,来源米客 * @return 返回一个 Boolean 值,true 为已加密,false 为未加密 * API 34 已弃用 DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING 属性值,官方说法如下 * This result code has never actually been used, so there is no reason for apps to check for it. */ fun isDeviceEncrypted(context: Context): Boolean { val policyMgr = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager val encryption = policyMgr.storageEncryptionStatus return encryption == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE || encryption == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/api/VoyagerApis.kt ================================================ package com.sevtinge.cemiuiler.utils.api import android.content.Context import android.util.TypedValue import android.view.Window import com.github.kyuubiran.ezxhelper.ClassUtils.getStaticObjectOrNullAs import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass import com.github.kyuubiran.ezxhelper.EzXHelper import com.sevtinge.cemiuiler.utils.api.LazyClass.clazzMiuiBuild import com.sevtinge.cemiuiler.utils.isStatic import java.lang.reflect.Field import java.lang.reflect.Method @JvmInline value class Args(val args: Array) @JvmInline value class ArgTypes(val argTypes: Array>) @Suppress("NOTHING_TO_INLINE") inline fun args(vararg args: Any?) = Args(args) @Suppress("NOTHING_TO_INLINE") inline fun argTypes(vararg argTypes: Class<*>) = ArgTypes(argTypes) typealias MethodCondition = Method.() -> Boolean /** * 扩展函数 通过类或者对象获取单个属性 * @param fieldName 属性名 * @param isStatic 是否静态类型 * @param fieldType 属性类型 * @return 符合条件的属性 * @throws IllegalArgumentException 属性名为空 * @throws NoSuchFieldException 未找到属性 */ fun Any.field( fieldName: String, isStatic: Boolean = false, fieldType: Class<*>? = null ): Field { if (fieldName.isBlank()) throw IllegalArgumentException("Field name must not be empty!") var c: Class<*> = if (this is Class<*>) this else this.javaClass do { c.declaredFields .filter { isStatic == it.isStatic } .firstOrNull { (fieldType == null || it.type == fieldType) && (it.name == fieldName) } ?.let { it.isAccessible = true;return it } } while (c.superclass?.also { c = it } != null) throw NoSuchFieldException("Name: $fieldName,Static: $isStatic, Type: ${if (fieldType == null) "ignore" else fieldType.name}") } /** * 判断运行模块的机型是否是平板 * @return 一个 Boolean 值,true 代表是平板,false 代表不是平板 * @author Voyager */ val IS_TABLET by lazy { getStaticObjectOrNullAs(clazzMiuiBuild, "IS_TABLET") ?: false } /** * 函数调用,适用于其他一些需要判断的情况 */ fun isPad() = clazzMiuiBuild.getField("IS_TABLET").getBoolean(null) /** * 是否为国际版系统 */ val IS_INTERNATIONAL_BUILD by lazy { getStaticObjectOrNullAs(clazzMiuiBuild, "IS_INTERNATIONAL_BUILD") ?: false } fun getValueByField(target: Any, fieldName: String, clazz: Class<*>? = null): Any? { var targetClass = clazz if (targetClass == null) { targetClass = target.javaClass } return try { val field = targetClass.getDeclaredField(fieldName) field.isAccessible = true field.get(target) } catch (e: Throwable) { if (targetClass.superclass == null) { null } else { getValueByField(target, fieldName, targetClass.superclass) } } } /** * 扩展函数 通过遍历方法数组 返回符合条件的方法数组 * @param condition 条件 * @return 符合条件的方法数组 */ fun Array.findAllMethods(condition: MethodCondition): Array { return this.filter { it.condition() }.onEach { it.isAccessible = true }.toTypedArray() } /** * 通过条件获取方法数组 * @param clz 类 * @param findSuper 是否查找父类 * @param condition 条件 * @return 符合条件的方法数组 */ fun findAllMethods( clz: Class<*>, findSuper: Boolean = false, condition: MethodCondition ): List { var c = clz val arr = ArrayList() arr.addAll(c.declaredMethods.findAllMethods(condition)) if (findSuper) { while (c.superclass?.also { c = it } != null) { arr.addAll(c.declaredMethods.findAllMethods(condition)) } } return arr } /** * 通过条件获取方法数组 * @param clzName 类名 * @param classLoader 类加载器 * @param findSuper 是否查找父类 * @param condition 条件 * @return 符合条件的方法数组 */ fun findAllMethods( clzName: String, classLoader: ClassLoader = EzXHelper.classLoader, findSuper: Boolean = false, condition: MethodCondition ): List { return findAllMethods(loadClass(clzName, classLoader), findSuper, condition) } fun dp2px(context: Context, dpValue: Float): Int = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dpValue, context.resources.displayMetrics ).toInt() /** * 模糊查找组件调用 */ object BlurDraw { fun getValueByFields(target: Any, fieldNames: List, clazz: Class<*>? = null): Any? { var targetClass = clazz ?: target.javaClass while (targetClass != Any::class.java) { for (fieldName in fieldNames) { try { val field = targetClass.getDeclaredField(fieldName) field.isAccessible = true val value = field.get(target) if (value is Window) { // Log.i("BlurPersonalAssistant Window field name: $fieldName") return value } } catch (e: NoSuchFieldException) { // This field doesn't exist in this class, skip it } catch (e: IllegalAccessException) { // This field isn't accessible, skip it } } targetClass = targetClass.superclass ?: break } return null } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/api/loadClassByLazy.kt ================================================ package com.sevtinge.cemiuiler.utils.api import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass // by StarVoyager object LazyClass { val clazzMiuiBuild by lazy { loadClass("miui.os.Build") } val AndroidBuildCls by lazy { loadClass("android.os.Build") } val SettingsFeaturesClass by lazy { loadClass("com.android.settings.utils.SettingsFeatures") } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/devicesdk/AppUtils.kt ================================================ package com.sevtinge.cemiuiler.utils.devicesdk import android.annotation.SuppressLint import android.content.Context import android.content.pm.PackageInfo import android.content.pm.PackageManager import android.content.res.Configuration import android.content.res.Resources import android.os.Build import android.text.TextUtils import android.util.Log import android.util.TypedValue import com.github.kyuubiran.ezxhelper.EzXHelper import com.sevtinge.cemiuiler.utils.PrefsUtils.getSharedPrefs import moralnorm.internal.utils.DeviceHelper import java.io.DataOutputStream import java.util.* fun dp2px(dpValue: Float): Int = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dpValue, EzXHelper.appContext.resources.displayMetrics ).toInt() fun dp2px2(dp: Float): Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, Resources.getSystem().displayMetrics) fun px2dp(pxValue: Int): Int = (pxValue / EzXHelper.appContext.resources.displayMetrics.density + 0.5f).toInt() fun getDensityDpi(): Int = (EzXHelper.appContext.resources.displayMetrics.widthPixels / EzXHelper.appContext.resources.displayMetrics.density).toInt() fun isDarkMode(): Boolean = EzXHelper.appContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES @SuppressLint("PrivateApi") @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") fun getProp(mKey: String): String = Class.forName("android.os.SystemProperties").getMethod("get", String::class.java) .invoke(Class.forName("android.os.SystemProperties"), mKey) .toString() @SuppressLint("PrivateApi") fun getProp(mKey: String, defaultValue: Boolean): Boolean = Class.forName("android.os.SystemProperties") .getMethod("getBoolean", String::class.java, Boolean::class.javaPrimitiveType) .invoke(Class.forName("android.os.SystemProperties"), mKey, defaultValue) as Boolean fun getPackageInfoCompat(packageName: String, flags: Int = 0): PackageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { EzXHelper.appContext.packageManager.getPackageInfo( packageName, PackageManager.PackageInfoFlags.of(flags.toLong()) ) } else { EzXHelper.appContext.packageManager.getPackageInfo(packageName, flags) } fun checkVersionName(): String = getPackageInfoCompat(EzXHelper.appContext.packageName).versionName fun isAlpha(): Boolean = getPackageInfoCompat(EzXHelper.appContext.packageName).versionName.contains("ALPHA", ignoreCase = true) fun isTablet(): Boolean = Resources.getSystem().getConfiguration().smallestScreenWidthDp >= 600 fun isPadDevice(): Boolean = isTablet() || DeviceHelper.isFoldDevice() fun checkVersionCode(): Long = getPackageInfoCompat(EzXHelper.appContext.packageName).longVersionCode fun checkAndroidVersion(): String = getProp("ro.build.version.release") /** * 执行 Shell 命令 * @param command Shell 命令 */ fun execShell(command: String) { try { val p = Runtime.getRuntime().exec("su") val outputStream = p.outputStream val dataOutputStream = DataOutputStream(outputStream) dataOutputStream.writeBytes(command) dataOutputStream.flush() dataOutputStream.close() outputStream.close() } catch (t: Throwable) { t.printStackTrace() } } @SuppressLint("DiscouragedApi") fun getCornerRadiusTop(): Int { val resourceId = EzXHelper.appContext.resources.getIdentifier( "rounded_corner_radius_top", "dimen", "android" ) return if (resourceId > 0) { EzXHelper.appContext.resources.getDimensionPixelSize(resourceId) } else 100 } fun setLocale(context: Context, locale: Locale): Context { var tmpLocale: Locale = locale if ("und" == locale.toLanguageTag() || "system" == locale.toLanguageTag()) { tmpLocale = Resources.getSystem().configuration.locales[0] } val configuration = context.resources.configuration configuration.setLocale(tmpLocale) Log.d("AppUtil", "setLocale: ${tmpLocale.toLanguageTag()}") // if (atLeastAndroidT()) { // AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(tmpLocale.toLanguageTag())) // } return context.createConfigurationContext(configuration) } fun getLocale(context: Context): Locale { val pref = getSharedPrefs(context, true) val tag: String? = pref.getString("prefs_key_settings_language", "SYSTEM") Log.d("AppUtil", "getLocale: tag=$tag") return if (tag == null || TextUtils.isEmpty(tag) || "SYSTEM" == tag) { val sysLang = Resources.getSystem().configuration.locales[0].toLanguageTag().trim() Log.d("AppUtil", "getLocale: sysLang=$sysLang") Locale.forLanguageTag(sysLang) } else Locale.forLanguageTag(tag) } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/devicesdk/SystemSDK.kt ================================================ package com.sevtinge.cemiuiler.utils.devicesdk import android.os.Build /** 获取设备 Android 版本 、MIUI 版本 并判断设备指定类型 */ fun getAndroidVersion(): Int = Build.VERSION.SDK_INT fun isAndroidR(): Boolean = getAndroidVersion() == Build.VERSION_CODES.R fun isAndroidS(): Boolean = getAndroidVersion() == Build.VERSION_CODES.S fun isAndroidSv2(): Boolean = getAndroidVersion() == Build.VERSION_CODES.S_V2 fun isAndroidT(): Boolean = getAndroidVersion() == Build.VERSION_CODES.TIRAMISU fun isAndroidU(): Boolean = getAndroidVersion() == Build.VERSION_CODES.UPSIDE_DOWN_CAKE fun isMoreAndroidVersion(version: Int): Boolean { return getAndroidVersion() >= version } fun getMiuiVersion(): Float = when (getProp("ro.miui.ui.version.name")) { "V150" -> 15f "V140" -> 14f "V130" -> 13f "V125" -> 12.5f "V12" -> 12f "V11" -> 11f "V10" -> 10f else -> 0f } fun isMoreMiuiVersion(version: Float): Boolean { return getMiuiVersion() >= version } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/log/AndroidLogUtils.java ================================================ package com.sevtinge.cemiuiler.utils.log; import android.util.Log; import com.sevtinge.cemiuiler.BuildConfig; import com.sevtinge.cemiuiler.module.base.BaseHook; /* 不太建议在非 Xposed 代码使用处调用,虽然已经做了 try 处理,但是 detailLog 将始终为 false * 可能因为 * 会导致 等 * */ public class AndroidLogUtils { private static final String Tag = "Cemiuiler]: "; private static final boolean isDebugVersion = BuildConfig.BUILD_TYPE.contains("debug"); private static final boolean isNotReleaseVersion = !BuildConfig.BUILD_TYPE.contains("release"); private static boolean detailLog = false; private static boolean run = false; private static void getDisableDetailedLog() { if (!run) { try { detailLog = BaseHook.mPrefsMap.getBoolean("settings_disable_detailed_log"); } catch (Throwable e) { LogE("getDisableDetailedLog", "It is not recommended to call this class in non Xposed code," + "detailLog will be false: ", e); } run = true; } } public static void LogI(String tag, String msg) { getDisableDetailedLog(); if (!isDebugVersion) return; if (detailLog) return; Log.i(tag, "[I/" + Tag + msg); } public static void deLogI(String tag, String msg) { Log.i(tag, "[I/" + Tag + msg); } public static void LogD(String tag, Throwable tr) { if (!isDebugVersion) return; Log.d(tag, "[D/" + Tag, tr); } public static void LogD(String tag, String msg, Throwable tr) { if (!isDebugVersion) return; Log.d(tag, "[D/" + Tag + msg, tr); } public static void LogE(String tag, Throwable tr) { if (!isDebugVersion) return; Log.e(tag, "[E/" + Tag, tr); } public static void LogE(String tag, String msg, Throwable tr) { if (!isDebugVersion) return; Log.e(tag, "[E/" + Tag + msg, tr); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/log/XposedLogUtils.java ================================================ package com.sevtinge.cemiuiler.utils.log; import java.util.Optional; import com.sevtinge.cemiuiler.BuildConfig; import com.sevtinge.cemiuiler.module.base.BaseHook; import de.robv.android.xposed.XposedBridge; public class XposedLogUtils { private static boolean isDebugVersion = BuildConfig.BUILD_TYPE.contains("debug"); private static boolean isReleaseVersion = BuildConfig.BUILD_TYPE.contains("release"); private static boolean isDisableDetailLog = BaseHook.mPrefsMap.getBoolean("settings_disable_detailed_log"); public static void logI(String msg) { if (!isDebugVersion) return; if (isDisableDetailLog) return; XposedBridge.log("[Cemiuiler][I]: " + msg); } public static void logI(String tag, String msg) { if (!isDebugVersion) return; if (isDisableDetailLog) return; XposedBridge.log("[Cemiuiler][I][" + tag + "]: " + msg); } public static void logW(String msg) { if (isReleaseVersion) return; if (isDisableDetailLog) return; XposedBridge.log("[Cemiuiler][W]: " + msg); } public static void logW(String tag, String msg) { if (isReleaseVersion) return; if (isDisableDetailLog) return; XposedBridge.log("[Cemiuiler][W][" + tag + "]: " + msg); } public static void logW(String tag, Throwable log) { if (isReleaseVersion) return; if (isDisableDetailLog) return; XposedBridge.log("[Cemiuiler][W][" + tag + "]: " + log); } public static void logW(String tag, String msg, Exception exp) { if (isReleaseVersion) return; if (isDisableDetailLog) return; XposedBridge.log("[Cemiuiler][W][" + tag + "]: " + msg + ", by" + exp); } public static void logW(String tag, String msg, Throwable log) { if (isReleaseVersion) return; if (isDisableDetailLog) return; XposedBridge.log("[Cemiuiler][W][" + tag + "]: " + msg + ", by" + log); } public static void logE(String tag, String msg) { XposedBridge.log("[Cemiuiler][E][" + tag + "]: " + msg); } public static void logE(String tag, Throwable log) { XposedBridge.log("[Cemiuiler][E][" + tag + "]: " + log); } public static void logE(String tag, Exception exp) { XposedBridge.log("[Cemiuiler][E][" + tag + "]: " + exp); } public static void logE(String tag, String msg, Throwable log) { XposedBridge.log("[Cemiuiler][E][" + tag + "]: " + msg + ", by" + log); } public static void logE(String tag, String msg, Exception exp) { XposedBridge.log("[Cemiuiler][E][" + tag + "]: " + msg + ", by" + exp); } public static void logD(String msg) { if (!isDebugVersion) return; XposedBridge.log("[Cemiuiler][D]: " + msg); } public static void logD(String tag, String msg) { if (!isDebugVersion) return; XposedBridge.log("[Cemiuiler][D][" + tag + "]: " + msg); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/utils/log/XposedLogUtilsKt.kt ================================================ package com.sevtinge.cemiuiler.utils.log import com.sevtinge.cemiuiler.BuildConfig import com.sevtinge.cemiuiler.module.base.BaseHook import de.robv.android.xposed.XposedBridge object XposedLogUtilsKt { private val isDebugVersion = BuildConfig.BUILD_TYPE.contains("debug") private val isNotReleaseVersion = !BuildConfig.BUILD_TYPE.contains("release") private val detailLog = BaseHook.mPrefsMap.getBoolean("settings_disable_detailed_log") // Xposed debug 日志输出 fun logI(tag: String?, msg: String) { if (!isDebugVersion) return if (detailLog) return if (tag != null) XposedBridge.log("[Cemiuiler][I][$tag]: $msg") else XposedBridge.log("[Cemiuiler][I]: $msg") } fun logW(tag: String, msg: String) { if (detailLog) return XposedBridge.log("[Cemiuiler][W][$tag]: $msg") } fun logW(tag: String, log: Throwable) { if (detailLog) return XposedBridge.log("[Cemiuiler][W][$tag]: $log") } fun logW(tag: String, msg: String, log: Throwable) { if (detailLog) return XposedBridge.log("[Cemiuiler][W][$tag]: $msg, warning by $log") } fun logE(tag: String, log: Throwable?, exp: Exception?) { val logMessage = "[Cemiuiler][E][$tag]: " + when { log != null -> ", hook failed by $log" exp != null -> ", hook failed by $exp" else -> "" } XposedBridge.log(logMessage) } fun logE(tag: String, msg: String, log: Throwable?, exp: Exception?) { val logMessage = "[Cemiuiler][E][$tag]: $msg" + when { log != null -> ", hook failed by $log" exp != null -> ", hook failed by $exp" else -> "" } XposedBridge.log(logMessage) } fun logD(tag: String, msg: String) { if (!isDebugVersion) return XposedBridge.log("[Cemiuiler][D][$tag]: $msg") } fun logD(msg: String) { if (!isDebugVersion) return XposedBridge.log("[Cemiuiler][D]: $msg") } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/view/BatteryIndicatorView.java ================================================ package com.sevtinge.cemiuiler.view; import android.animation.ArgbEvaluator; import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Shader; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.RectShape; import android.graphics.drawable.shapes.RoundRectShape; import android.net.Uri; import android.os.Handler; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import com.sevtinge.cemiuiler.utils.PrefsUtils; import de.robv.android.xposed.XposedHelpers; public class BatteryIndicatorView extends ImageView { protected int mDisplayWidth; protected boolean mIsBeingCharged; protected boolean mIsExtremePowerSave; protected boolean mIsPowerSave; @SuppressLint("DiscouragedApi") protected final int mLowLevelSystem = getResources().getInteger(getResources().getIdentifier("config_lowBatteryWarningLevel", "integer", "android")); protected int mPowerLevel; protected int mTestPowerLevel; private int mFullColor = Color.GREEN; private int mLowColor = Color.RED; private int mPowerSaveColor = Color.rgb(245, 166, 35); private int mChargingColor = Color.YELLOW; private int mLowLevel = mLowLevelSystem; private int mHeight = 5; private int mGlow = 0; private int mTransparency = 0; private int mPadding = 0; private int mVisibility = View.VISIBLE; private ColorMode mColorMode = ColorMode.DISCRETE; private boolean mTesting = false; private boolean mRounded = false; private boolean mCentered = false; private boolean mExpanded = false; private boolean mOnKeyguard = false; private boolean mBottom = false; private boolean mLimited = false; private int mTintColor = Color.argb(153, 0, 0, 0); private Object mStatusBar = null; enum ColorMode { DISCRETE, GRADUAL, RAINBOW } public BatteryIndicatorView(Context context) { super(context); updateDisplaySize(); } public BatteryIndicatorView(Context context, AttributeSet attributeSet) { super(context, attributeSet); updateDisplaySize(); } public void init(Object statusBar) { mStatusBar = statusBar; try { ShapeDrawable shape = new ShapeDrawable(); Paint paint = shape.getPaint(); paint.setStyle(Paint.Style.FILL); paint.setAntiAlias(true); shape.setIntrinsicWidth(9999); setImageDrawable(shape); } catch (Throwable t) { } updateParameters(); new PrefsUtils.SharedPrefsObserver(getContext(), new Handler(getContext().getMainLooper())) { @Override public void onChange(Uri uri) { try { String key = uri.getPathSegments().get(2); if (!mTesting) { updateParameters(); update(); } } catch (Throwable t) { } } }; getContext().registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { removeCallbacks(step); startTest(); } }, new IntentFilter("moralnorm.module.BatteryIndicatorTest")); } Runnable step = new Runnable() { @Override public void run() { mTestPowerLevel--; if (mTestPowerLevel >= 0) { update(); postDelayed(step, mTestPowerLevel == mLowLevel - 1 ? 300 : 20); } else { removeCallbacks(step); mTesting = false; postDelayed(() -> { updateParameters(); update(); }, 1000); } } }; private void startTest() { mTesting = true; mTestPowerLevel = 100; post(step); } private void postUpdate() { post(BatteryIndicatorView.this::update); } public void onExpandingChanged(boolean expanded) { if (mExpanded == expanded) return; mExpanded = expanded; update(); } public void onKeyguardStateChanged(boolean showing) { if (mOnKeyguard == showing) return; mOnKeyguard = showing; update(); } public void onDarkModeChanged(float intensity, int tintColor) { // if (intensity != 0.0f && intensity != 1.0f) return; if (mTintColor == tintColor) return; mTintColor = tintColor; update(); } public void onBatteryLevelChanged(int powerLevel, boolean isCharging, boolean isCharged) { if (this.mPowerLevel == powerLevel && this.mIsBeingCharged == isCharging && !isCharged) return; this.mPowerLevel = powerLevel; this.mIsBeingCharged = isCharging && !isCharged; // if (isCharging != this.mIsCharged) { // this.mIsCharged = isCharging; // if (!this.mIsCharged) // startChargingAnim(); // else // stopChargingAnim(); // } update(); } public void onPowerSaveChanged(boolean isPowerSave) { if (this.mIsPowerSave == isPowerSave) return; this.mIsPowerSave = isPowerSave; update(); } public void onExtremePowerSaveChanged(boolean isExtremePowerSave) { if (this.mIsExtremePowerSave == isExtremePowerSave) return; this.mIsExtremePowerSave = isExtremePowerSave; update(); } @Override protected void onConfigurationChanged(Configuration configuration) { super.onConfigurationChanged(configuration); updateDisplaySize(); postUpdate(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (changed) { updateDisplaySize(); postUpdate(); } } public void update() { if (mLimited) this.setVisibility(mExpanded || mOnKeyguard ? mVisibility : View.GONE); clearAnimation(); updateDrawable(); } public void updateDisplaySize() { this.mDisplayWidth = getMeasuredWidth(); } protected void updateParameters() { mColorMode = ColorMode.values()[Integer.parseInt(PrefsUtils.getSharedStringPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_color", "0"))]; mFullColor = PrefsUtils.getSharedIntPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_color_full_power", Color.GREEN); mLowColor = PrefsUtils.getSharedIntPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_color_low_power", Color.RED); mPowerSaveColor = PrefsUtils.getSharedIntPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_color_power_saving", Color.rgb(245, 166, 35)); mChargingColor = PrefsUtils.getSharedIntPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_color_power_charging", Color.YELLOW); mLowLevel = PrefsUtils.getSharedIntPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_low_level", mLowLevelSystem); mHeight = PrefsUtils.getSharedIntPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_height", 5); mGlow = PrefsUtils.getSharedIntPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_glow", 0); mRounded = PrefsUtils.getSharedBoolPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_rounded", false); mBottom = Integer.parseInt(PrefsUtils.getSharedStringPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_align", "0")) == 1; mCentered = PrefsUtils.getSharedBoolPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_centered", false); mLimited = PrefsUtils.getSharedBoolPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_limitvis", false); mTransparency = PrefsUtils.getSharedIntPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_alpha", 0); mPadding = PrefsUtils.getSharedIntPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_padding", 0); mVisibility = PrefsUtils.getSharedBoolPrefs(getContext(), "prefs_key_system_ui_status_bar_battery_indicator_enable", false) ? View.VISIBLE : View.GONE; FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); lp.width = ViewGroup.LayoutParams.MATCH_PARENT; lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; lp.gravity = mBottom ? Gravity.BOTTOM : Gravity.TOP; setLayoutParams(lp); try { this.setImageAlpha(255 - Math.round(255 * mTransparency / 100f)); } catch (Throwable ignore) { } this.setVisibility(mVisibility); this.setScaleType(mCentered ? ScaleType.CENTER : ScaleType.MATRIX); Matrix matrix = new Matrix(); matrix.setTranslate(0, 0); matrix.setScale(1, 1); this.setImageMatrix(new Matrix()); } @SuppressLint({"InternalInsetResource", "DiscouragedApi"}) protected void updateDrawable() { try { int level = this.mTesting ? this.mTestPowerLevel : this.mPowerLevel; int color = this.mFullColor; if (!this.mTesting && this.mIsBeingCharged) color = this.mChargingColor; else if (!this.mTesting && (this.mIsPowerSave || this.mIsExtremePowerSave)) color = this.mPowerSaveColor; else if (level <= this.mLowLevel) color = this.mLowColor; ShapeDrawable shape = (ShapeDrawable) getDrawable(); shape.setShaderFactory(null); Paint paint = shape.getPaint(); paint.setShader(null); if (color == Color.TRANSPARENT && mStatusBar != null) try { if (mExpanded) { color = Color.WHITE; } else { if (mOnKeyguard) { boolean isLightWallpaperStatusBar = (boolean) XposedHelpers.callMethod(XposedHelpers.getObjectField(mStatusBar, "mUpdateMonitor"), "isLightWallpaperStatusBar"); color = (isLightWallpaperStatusBar ? Color.argb(153, 0, 0, 0) : Color.WHITE); } else { color = mTintColor; } } } catch (Throwable t) { } int mDisplayPadding = Math.round(mPadding / 100f * this.mDisplayWidth); if (mColorMode == ColorMode.GRADUAL) { color = level <= this.mLowLevel || (!this.mTesting && (this.mIsBeingCharged || this.mIsPowerSave || this.mIsExtremePowerSave)) ? color : (int) new ArgbEvaluator().evaluate(1f - (level - this.mLowLevel) / (100f - this.mLowLevel), color, mLowColor); } else if (mColorMode == ColorMode.RAINBOW) { int steps = 15; float jump = 300f / (float) steps; float[] pos = new float[steps]; int[] rainbow = new int[steps]; for (int i = 0; i < steps; i++) { pos[i] = i / (float) (steps - 1); float c = (mCentered ? 240 : 0) + jump * i; if (c > 360) c -= 360; rainbow[i] = Color.HSVToColor(255, new float[]{c, 1.0f, 1.0f}); } shape.setShaderFactory(new ShapeDrawable.ShaderFactory() { @Override public Shader resize(int width, int height) { if (mCentered) return new LinearGradient(width / 2f - (mDisplayWidth - mDisplayPadding * 2) / 2f, height / 2f, (mDisplayWidth - mDisplayPadding * 2), height / 2f, rainbow, pos, Shader.TileMode.CLAMP); else return new LinearGradient(0, height / 2f, (mDisplayWidth - mDisplayPadding * 2), height / 2f, rainbow, pos, Shader.TileMode.CLAMP); } }); } paint.setColor(color); shape.setShape(mRounded ? new RoundRectShape(new float[]{mHeight, mHeight, mHeight, mHeight, mHeight, mHeight, mHeight, mHeight}, null, null) : new RectShape()); int mWidth = Math.round((this.mDisplayWidth - mDisplayPadding * 2) * level / 100f); float mDensity = getResources().getDisplayMetrics().density; int sbHeight = getResources().getDimensionPixelSize(getResources().getIdentifier("status_bar_height", "dimen", "android")); if (mGlow == 0) { paint.clearShadowLayer(); if (mBottom) setPadding(mDisplayPadding, 0, mDisplayPadding, -mHeight); else setPadding(mDisplayPadding, -mHeight, mDisplayPadding, 0); shape.setIntrinsicHeight(mHeight * 2); shape.setIntrinsicWidth(mWidth); } else { int shadowPadding = sbHeight - mHeight; paint.setShadowLayer( (mGlow / 100f) * (sbHeight - 9 * mDensity), (mCentered || mDisplayPadding > 0) ? 0 : shadowPadding / 2f, mBottom ? mHeight - 10 : 10 - mHeight, Color.argb(Math.min(Math.round(mGlow / 100f * 255), Math.round(255 - mTransparency / 100f * 255)), Color.red(color), Color.green(color), Color.blue(color)) ); if (mDisplayPadding == 0) setPadding(mCentered ? 0 : -shadowPadding, mBottom ? shadowPadding : -shadowPadding, mCentered ? 0 : Math.min(mDisplayWidth - mWidth, shadowPadding), mBottom ? -shadowPadding : shadowPadding); else setPadding(mDisplayPadding, mBottom ? shadowPadding : -shadowPadding, mDisplayPadding, mBottom ? -shadowPadding : shadowPadding); shape.setIntrinsicHeight(sbHeight); shape.setIntrinsicWidth(mWidth + (mCentered ? 0 : (mDisplayPadding == 0 ? shadowPadding : 0))); } invalidate(); } catch (Throwable t) { } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/view/BlurFrameLayout.java ================================================ package com.sevtinge.cemiuiler.view; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Build; import android.text.TextUtils; import android.view.View; import android.widget.FrameLayout; import androidx.annotation.RequiresApi; import com.sevtinge.cemiuiler.XposedInit; import com.sevtinge.cemiuiler.utils.DisplayUtils; import de.robv.android.xposed.XposedHelpers; @RequiresApi(Build.VERSION_CODES.S) public class BlurFrameLayout { int mBgColor; int mBgAlpha; int mBgCornerRadius; int mBlurRadius; boolean isBlurEnable; Context mContext; Drawable mBlurDrawable; Object mViewRootImpl; View mBlurView; public BlurFrameLayout(Context context, boolean blurEnable) { isBlurEnable = blurEnable; } public BlurFrameLayout(View view, String key) { this(view.getContext(), false); mContext = view.getContext(); mBlurView = new FrameLayout(mContext); if (!TextUtils.isEmpty(key)) { String mBgColorKey = key + "_bg_color"; String mBgAlphaKey = key + "_bg_alpha"; String mBgCornerRadiusKey = key + "_bg_corner_radius"; String mBlurRadiusKey = key + "_blur_radius"; mBlurRadius = XposedInit.mPrefsMap.getInt(mBlurRadiusKey, 60); mBgColor = XposedInit.mPrefsMap.getInt(mBgColorKey, -1); mBgAlpha = XposedInit.mPrefsMap.getInt(mBgAlphaKey, 60); mBgCornerRadius = DisplayUtils.dip2px(mContext, XposedInit.mPrefsMap.getInt(mBgCornerRadiusKey, 90)); } setOnAttachStateChangeListener(mBlurView); } private void setOnAttachStateChangeListener(View view) { view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { mViewRootImpl = XposedHelpers.callMethod(v, "getViewRootImpl"); mBlurDrawable = (Drawable) XposedHelpers.callMethod(mViewRootImpl, "createBackgroundBlurDrawable", new Object[0]); setBackgroundDrawable(mContext, v, isBlurEnable, mBgColor, mBgAlpha, mBgCornerRadius, mBlurRadius); } @Override public void onViewDetachedFromWindow(View v) { v.setBackground(null); } }); } private void setBackgroundDrawable(Context context, View view, boolean isBlurEnable, int color, int alpha, int cornerRadius, int blurRadius) { if (isBlurEnable) { setColor(color, alpha); setCornerRadius(cornerRadius); setBlurRadius(blurRadius); } else { view.setBackground(createGradientDrawable(context, color, alpha, cornerRadius)); } } public void setColor(int color, int alpha) { int mColorRed = (color & 0x00ff0000) >> 16; int mColorGreen = (color & 0x0000ff00) >> 8; int mColorBlue = (color & 0x000000ff); XposedHelpers.callMethod(mBlurDrawable, "setColor", Color.argb(alpha, mColorRed, mColorGreen, mColorBlue)); } public void setCornerRadius(int cornerRadius) { XposedHelpers.callMethod(mBlurDrawable, "setCornerRadius", cornerRadius); } public void setBlurRadius(int blurRadius) { XposedHelpers.callMethod(mBlurDrawable, "setBlurRadius", blurRadius); } private GradientDrawable createGradientDrawable(Context context, int color, int alpha, int cornerRadius) { int mColorRed = (color & 0x00ff0000) >> 16; int mColorGreen = (color & 0x0000ff00) >> 8; int mColorBlue = (color & 0x000000ff); GradientDrawable mBackgroundDrawable = new GradientDrawable(); mBackgroundDrawable.setShape(GradientDrawable.RECTANGLE); mBackgroundDrawable.setColor(Color.argb(alpha, mColorRed, mColorGreen, mColorBlue)); mBackgroundDrawable.setCornerRadius(DisplayUtils.dip2px(context, cornerRadius)); return mBackgroundDrawable; } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/view/CircleImageView.java ================================================ package com.sevtinge.cemiuiler.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.util.AttributeSet; import android.widget.ImageView; import com.sevtinge.cemiuiler.R; import androidx.annotation.ColorInt; import androidx.annotation.ColorRes; import androidx.annotation.DrawableRes; public class CircleImageView extends ImageView { private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; private static final int COLORDRAWABLE_DIMENSION = 2; private static final int DEFAULT_BORDER_WIDTH = 0; private static final int DEFAULT_BORDER_COLOR = Color.BLACK; private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT; private static final boolean DEFAULT_BORDER_OVERLAY = false; private final RectF mDrawableRect = new RectF(); private final RectF mBorderRect = new RectF(); private final Matrix mShaderMatrix = new Matrix(); private final Paint mBitmapPaint = new Paint(); private final Paint mBorderPaint = new Paint(); private final Paint mFillPaint = new Paint(); private int mBorderColor = DEFAULT_BORDER_COLOR; private int mBorderWidth = DEFAULT_BORDER_WIDTH; private int mFillColor = DEFAULT_FILL_COLOR; private Bitmap mBitmap; private BitmapShader mBitmapShader; private int mBitmapWidth; private int mBitmapHeight; private float mDrawableRadius; private float mBorderRadius; private ColorFilter mColorFilter; private boolean mReady; private boolean mSetupPending; private boolean mBorderOverlay; public CircleImageView(Context context) { super(context); init(); } public CircleImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR); mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_border_overlay, DEFAULT_BORDER_OVERLAY); mFillColor = a.getColor(R.styleable.CircleImageView_fill_color1, DEFAULT_FILL_COLOR); a.recycle(); init(); } private void init() { super.setScaleType(SCALE_TYPE); mReady = true; if (mSetupPending) { setup(); mSetupPending = false; } } @Override public ScaleType getScaleType() { return SCALE_TYPE; } @Override public void setScaleType(ScaleType scaleType) { if (scaleType != SCALE_TYPE) { throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); } } @Override public void setAdjustViewBounds(boolean adjustViewBounds) { if (adjustViewBounds) { throw new IllegalArgumentException("adjustViewBounds not supported."); } } @Override protected void onDraw(Canvas canvas) { if (mBitmap == null) { return; } if (mFillColor != Color.TRANSPARENT) { canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mFillPaint); } canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mDrawableRadius, mBitmapPaint); if (mBorderWidth != 0) { canvas.drawCircle(getWidth() / 2.0f, getHeight() / 2.0f, mBorderRadius, mBorderPaint); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); setup(); } public int getBorderColor() { return mBorderColor; } public void setBorderColor(@ColorInt int borderColor) { if (borderColor == mBorderColor) { return; } mBorderColor = borderColor; mBorderPaint.setColor(mBorderColor); invalidate(); } public void setBorderColorResource(@ColorRes int borderColorRes) { setBorderColor(getContext().getResources().getColor(borderColorRes, null)); } public int getFillColor() { return mFillColor; } public void setFillColor(@ColorInt int fillColor) { if (fillColor == mFillColor) { return; } mFillColor = fillColor; mFillPaint.setColor(fillColor); invalidate(); } public void setFillColorResource(@ColorRes int fillColorRes) { setFillColor(getContext().getResources().getColor(fillColorRes, null)); } public int getBorderWidth() { return mBorderWidth; } public void setBorderWidth(int borderWidth) { if (borderWidth == mBorderWidth) { return; } mBorderWidth = borderWidth; setup(); } public boolean isBorderOverlay() { return mBorderOverlay; } public void setBorderOverlay(boolean borderOverlay) { if (borderOverlay == mBorderOverlay) { return; } mBorderOverlay = borderOverlay; setup(); } @Override public void setImageBitmap(Bitmap bm) { super.setImageBitmap(bm); mBitmap = bm; setup(); } @Override public void setImageDrawable(Drawable drawable) { super.setImageDrawable(drawable); mBitmap = getBitmapFromDrawable(drawable); setup(); } @Override public void setImageResource(@DrawableRes int resId) { super.setImageResource(resId); mBitmap = getBitmapFromDrawable(getDrawable()); setup(); } @Override public void setImageURI(Uri uri) { super.setImageURI(uri); mBitmap = uri != null ? getBitmapFromDrawable(getDrawable()) : null; setup(); } @Override public void setColorFilter(ColorFilter cf) { if (cf == mColorFilter) { return; } mColorFilter = cf; mBitmapPaint.setColorFilter(mColorFilter); invalidate(); } private Bitmap getBitmapFromDrawable(Drawable drawable) { if (drawable == null) { return null; } if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } try { Bitmap bitmap; if (drawable instanceof ColorDrawable) { bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } catch (Exception e) { e.printStackTrace(); return null; } } private void setup() { if (!mReady) { mSetupPending = true; return; } if (getWidth() == 0 && getHeight() == 0) { return; } if (mBitmap == null) { invalidate(); return; } mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapPaint.setAntiAlias(true); mBitmapPaint.setShader(mBitmapShader); mBorderPaint.setStyle(Paint.Style.STROKE); mBorderPaint.setAntiAlias(true); mBorderPaint.setColor(mBorderColor); mBorderPaint.setStrokeWidth(mBorderWidth); mFillPaint.setStyle(Paint.Style.FILL); mFillPaint.setAntiAlias(true); mFillPaint.setColor(mFillColor); mBitmapHeight = mBitmap.getHeight(); mBitmapWidth = mBitmap.getWidth(); mBorderRect.set(0, 0, getWidth(), getHeight()); mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f); mDrawableRect.set(mBorderRect); if (!mBorderOverlay) { mDrawableRect.inset(mBorderWidth, mBorderWidth); } mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f); updateShaderMatrix(); invalidate(); } private void updateShaderMatrix() { float scale; float dx = 0; float dy = 0; mShaderMatrix.set(null); if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { scale = mDrawableRect.height() / (float) mBitmapHeight; dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; } else { scale = mDrawableRect.width() / (float) mBitmapWidth; dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; } mShaderMatrix.setScale(scale, scale); mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top); mBitmapShader.setLocalMatrix(mShaderMatrix); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/view/MultipleChoiceView.java ================================================ package com.sevtinge.cemiuiler.view; import android.content.Context; import android.util.AttributeSet; import android.util.SparseBooleanArray; import android.view.View; import android.widget.Button; import android.widget.LinearLayout; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.data.adapter.MutipleChoiceAdapter; import java.util.List; public class MultipleChoiceView extends LinearLayout implements MutipleChoiceAdapter.OnCurWillCheckAllChangedListener { private MutipleChoiceAdapter mAdapter; private List mData; private RecyclerView mListView; private Button mAllSelectBtn; private Button mOkBtn; // 确定选择监听器 private onCheckedListener mOnCheckedListener; // 当前点击按钮时是否将全选 private boolean curWillCheckAll = true; public MultipleChoiceView(Context context) { super(context); initView(context); } public MultipleChoiceView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); initView(context); } /* 实例化各个控件 */ private void initView(Context context) { View view = inflate(context, R.layout.view_mutiplechoice, this); mListView = view.findViewById(android.R.id.list); mListView.setLayoutManager(new LinearLayoutManager(context)); mListView.setHasFixedSize(true); mAllSelectBtn = view.findViewById(android.R.id.button2); mOkBtn = view.findViewById(android.R.id.button1); mAllSelectBtn.setText(curWillCheckAll ? getResources().getString(R.string.appcompat_action_mode_select_all) : getResources().getString(R.string.appcompat_action_mode_inverse)); OnCustomMultipleChoiceCheckedListener onCheckedListener = new OnCustomMultipleChoiceCheckedListener(); // 全选按钮的回调接口 mAllSelectBtn.setOnClickListener(onCheckedListener); mOkBtn.setOnClickListener(onCheckedListener); } public void setData(List data, boolean[] isSelected) { if (data != null) { mData = data; mAdapter = new MutipleChoiceAdapter(data); mAdapter.setOnCurWillCheckAllChangedListener(this); if (isSelected != null) { if (isSelected.length != data.size()) { throw new IllegalArgumentException("data's length not equal the isSelected's length"); } else { for (int i = 0; i < isSelected.length; i++) { mAdapter.getCheckedArray().put(i, isSelected[i]); } } } // 绑定Adapter mListView.setAdapter(mAdapter); } else { throw new IllegalArgumentException("data is null"); } } public void setOnCheckedListener(onCheckedListener listener) { mOnCheckedListener = listener; } @Override public void onCurWillCheckAllChanged(boolean curWillCheckAll) { this.curWillCheckAll = curWillCheckAll; mAllSelectBtn.setText(curWillCheckAll ? getResources().getString(R.string.appcompat_action_mode_select_all) : getResources().getString(R.string.appcompat_action_mode_inverse)); } public interface onCheckedListener { void onChecked(SparseBooleanArray sparseBooleanArray); } /** * 全选 */ public void selectAll() { if (mData != null) { for (int i = 0; i < mData.size(); i++) { mAdapter.getCheckedArray().put(i, true); } // 刷新listview和TextView的显示 mAdapter.notifyDataSetChanged(); } } /** * 全不选 */ public void deselectAll() { if (mData != null) { for (int i = 0; i < mData.size(); i++) { mAdapter.getCheckedArray().put(i, false); } // 刷新listview和TextView的显示 mAdapter.notifyDataSetChanged(); } } /** * 反选 */ public void reverseSelect() { if (mData != null) { for (int i = 0; i < mData.size(); i++) { mAdapter.getCheckedArray().put(i, !mAdapter.getCheckedArray().get(i)); } // 刷新listview和TextView的显示 mAdapter.notifyDataSetChanged(); } } private class OnCustomMultipleChoiceCheckedListener implements OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { // 确定选择按钮 case android.R.id.button1 -> { if (mOnCheckedListener != null && mAdapter != null) { mOnCheckedListener.onChecked(mAdapter.getCheckedArray()); } } // 全选/反选按钮 case android.R.id.button2 -> { if (mData != null) { if (curWillCheckAll) { selectAll(); } else { reverseSelect(); } ((Button) v).setText(curWillCheckAll ? getResources().getString(R.string.appcompat_action_mode_inverse) : getResources().getString(R.string.appcompat_action_mode_select_all)); curWillCheckAll = !curWillCheckAll; } } } } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/view/RestartAlertDialog.java ================================================ package com.sevtinge.cemiuiler.view; import android.content.Context; import android.content.Intent; import android.content.res.Resources; import com.sevtinge.cemiuiler.R; import com.sevtinge.cemiuiler.module.app.GlobalActions; import com.sevtinge.cemiuiler.utils.ShellUtils; import java.util.Arrays; import java.util.List; import moralnorm.appcompat.app.AlertDialog; public class RestartAlertDialog extends AlertDialog { List mAppNameList; List mAppPackageNameList; public RestartAlertDialog(Context context) { super(context); setView(createMultipleChoiceView(context)); } private MultipleChoiceView createMultipleChoiceView(Context context) { Resources mRes = context.getResources(); MultipleChoiceView view = new MultipleChoiceView(context); mAppNameList = Arrays.asList(mRes.getStringArray(R.array.restart_apps_name)); mAppPackageNameList = Arrays.asList(mRes.getStringArray(R.array.restart_apps_packagename)); view.setData(mAppNameList, null); view.deselectAll(); view.setOnCheckedListener(sparseBooleanArray -> { dismiss(); for (int i = 0; i < sparseBooleanArray.size(); i++) { if (sparseBooleanArray.get(i)) { ShellUtils.execCommand("pkill -l 9 -f " + mAppPackageNameList.get(i), true, false); } } }); return view; } public void restartApp(Context context, String packageName) { Intent intent = new Intent(GlobalActions.ACTION_PREFIX + "RestartApps"); intent.putExtra("packageName", packageName); context.sendBroadcast(intent); } public void restartSystemUI(Context context) { Intent intent = new Intent(GlobalActions.ACTION_PREFIX + "RestartSystemUI"); intent.setPackage("com.android.systemui"); context.sendBroadcast(intent); } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/view/SpinnerEx.java ================================================ package com.sevtinge.cemiuiler.view; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import java.util.ArrayList; import moralnorm.appcompat.widget.Spinner; public class SpinnerEx extends Spinner { public CharSequence[] entries; public int[] entryValues; private final ArrayList disabledItems = new ArrayList<>(); public SpinnerEx(Context context, AttributeSet attrs) { super(context, attrs); final TypedArray xmlAttrs = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.entries, 0}); entries = xmlAttrs.getTextArray(0); if (xmlAttrs.getResourceId(1, 0) != 0) entryValues = getResources().getIntArray(xmlAttrs.getResourceId(1, 0)); xmlAttrs.recycle(); } private int findIndex(int val, int[] vals) { for (int i = 0; i < vals.length; i++) if (vals[i] == val) return i; return -1; } public void init(int val) { if (entries == null || entryValues == null) return; ArrayAdapterEx newAdapter = new ArrayAdapterEx(getContext(), android.R.layout.simple_spinner_item, entries); setAdapter(newAdapter); setSelection(findIndex(val, entryValues)); } public void addDisabledItems(int item) { disabledItems.add(item); } public int getSelectedArrayValue() { return entryValues[getSelectedItemPosition()]; } class ArrayAdapterEx extends ArrayAdapter { ArrayAdapterEx(Context context, int resource, CharSequence[] objects) { super(context, resource, objects); } @Override public boolean isEnabled(int position) { return !disabledItems.contains(position); } @Override public View getDropDownView(int position, View convertView, ViewGroup parent) { View view = super.getDropDownView(position, convertView, parent); view.setEnabled(isEnabled(position)); return view; } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/view/WeatherData.kt ================================================ package com.sevtinge.cemiuiler.view import android.annotation.SuppressLint import android.content.ComponentName import android.content.Context import android.content.Intent import android.database.ContentObserver import android.net.Uri import android.os.Handler import android.os.Looper import android.os.Message import android.text.TextUtils import android.widget.Toast import com.sevtinge.cemiuiler.utils.api.argTypes import com.sevtinge.cemiuiler.utils.api.args import com.sevtinge.cemiuiler.utils.callStaticMethod @SuppressLint("ViewConstructor", "SetTextI18n") class WeatherData(val context: Context?, private val showCity: Boolean) { private val mContext: Context private val mWeatherUri = Uri.parse("content://weather/weather") private val mHandler: Handler private val mWeatherObserver: ContentObserver? private val mWeatherRunnable: WeatherRunnable var weatherData: String = "\n" var callBacks: () -> Unit = {} init { mHandler = object : Handler(Looper.getMainLooper()) { override fun handleMessage(message: Message) { val str = message.obj as String weatherData = if (TextUtils.isEmpty(str)) "\n" else "$str\n" callBacks() } } mWeatherObserver = WeatherContentObserver(mHandler) mContext = context!! mWeatherRunnable = WeatherRunnable() context.contentResolver.registerContentObserver(mWeatherUri, true, mWeatherObserver) updateWeatherInfo() } private inner class WeatherContentObserver(handler: Handler?) : ContentObserver(handler) { override fun onChange(z: Boolean) { updateWeatherInfo() } } inner class WeatherRunnable : Runnable { override fun run() { var str = "" try { val query = mContext.contentResolver.query(mWeatherUri, null, null, null, null) if (query != null) { if (query.moveToFirst()) { str = if (showCity) { query.getString(query.getColumnIndexOrThrow("city_name")) + " " + query.getString( query.getColumnIndexOrThrow( "description" ) ) + " " + query.getString(query.getColumnIndexOrThrow("temperature")) } else { query.getString(query.getColumnIndexOrThrow("description")) + " " + query.getString( query.getColumnIndexOrThrow( "temperature" ) ) } } query.close() } } catch (_: Exception) { } val obtainMessage2 = mHandler.obtainMessage() obtainMessage2.what = 100 obtainMessage2.obj = str mHandler.sendMessage(obtainMessage2) } } private fun updateWeatherInfo() { mHandler.removeCallbacks(mWeatherRunnable) mHandler.postDelayed(mWeatherRunnable, 200) } fun onDetachedFromWindow() { if (mWeatherObserver != null) { mContext.contentResolver.unregisterContentObserver(mWeatherObserver) } } fun startCalendarApp() { mContext.classLoader.loadClass("com.miui.systemui.util.CommonUtil") .callStaticMethod("startCalendarApp", args(context), argTypes(Context::class.java)) } fun startWeatherApp() { try { val intent = Intent().apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK component = ComponentName( "com.miui.weather2", "com.miui.weather2.ActivityWeatherMain" ) } mContext.startActivity(intent) } catch (e: Exception) { Toast.makeText(context, "启动失败", Toast.LENGTH_LONG).show() } } } ================================================ FILE: app/src/main/java/com/sevtinge/cemiuiler/view/WeatherView.kt ================================================ package com.sevtinge.cemiuiler.view import android.annotation.SuppressLint import android.content.Context import android.database.ContentObserver import android.net.Uri import android.os.Handler import android.os.Looper import android.os.Message import android.text.TextUtils import android.widget.TextView @SuppressLint("ViewConstructor") class WeatherView(context: Context?, private val showCity: Boolean) : TextView(context) { private val mContext: Context private val weatherUri = Uri.parse("content://weather/weather") private val mHandler: Handler private val mWeatherObserver: ContentObserver? private val mWeatherRunnable: WeatherRunnable init { mHandler = object : Handler(Looper.getMainLooper()) { override fun handleMessage(message: Message) { val str = message.obj as String this@WeatherView.text = if (TextUtils.isEmpty(str)) " " else str } } mWeatherObserver = WeatherContentObserver(mHandler) mContext = context!! mWeatherRunnable = WeatherRunnable() context.contentResolver.registerContentObserver(weatherUri, true, mWeatherObserver) updateWeatherInfo() } private inner class WeatherContentObserver(handler: Handler?) : ContentObserver(handler) { override fun onChange(z: Boolean) { updateWeatherInfo() } } inner class WeatherRunnable : Runnable { override fun run() { var str = "" try { val query = mContext.contentResolver.query(weatherUri, null, null, null, null) if (query != null) { if (query.moveToFirst()) { str = if (showCity) { query.getString(query.getColumnIndexOrThrow("city_name")) + " " + query.getString( query.getColumnIndexOrThrow( "description" ) ) + " " + query.getString(query.getColumnIndexOrThrow("temperature")) } else { query.getString(query.getColumnIndexOrThrow("description")) + " " + query.getString( query.getColumnIndexOrThrow( "temperature" ) ) } } query.close() } } catch (_: Exception) { } val obtainMessage2 = mHandler.obtainMessage() obtainMessage2.what = 100 obtainMessage2.obj = str mHandler.sendMessage(obtainMessage2) } } private fun updateWeatherInfo() { mHandler.removeCallbacks(mWeatherRunnable) mHandler.postDelayed(mWeatherRunnable, 200) } public override fun onDetachedFromWindow() { super.onDetachedFromWindow() if (mWeatherObserver != null) { mContext.contentResolver.unregisterContentObserver(mWeatherObserver) } } } ================================================ FILE: app/src/main/java/com/zhenxiang/blur/BackgroundBlurDrawableExtensions.kt ================================================ package com.zhenxiang.blur import android.os.Build import androidx.annotation.RequiresApi import com.android.internal.graphics.drawable.BackgroundBlurDrawable import org.lsposed.hiddenapibypass.HiddenApiBypass @RequiresApi(Build.VERSION_CODES.S) fun BackgroundBlurDrawable.setColor(color: Int) { HiddenApiBypass.invoke(BackgroundBlurDrawable::class.java, this, "setColor", color) } @RequiresApi(Build.VERSION_CODES.S) fun BackgroundBlurDrawable.setBlurRadius(blurRadius: Int) { HiddenApiBypass.invoke(BackgroundBlurDrawable::class.java, this, "setBlurRadius", blurRadius) } @RequiresApi(Build.VERSION_CODES.S) fun BackgroundBlurDrawable.setCornerRadius( cornerRadiusTL: Float, cornerRadiusTR: Float, cornerRadiusBL: Float, cornerRadiusBR: Float ) { HiddenApiBypass.invoke( BackgroundBlurDrawable::class.java, this, "setCornerRadius", cornerRadiusTL, cornerRadiusTR, cornerRadiusBL, cornerRadiusBR ) } ================================================ FILE: app/src/main/java/com/zhenxiang/blur/BlurFrameLayout.kt ================================================ package com.zhenxiang.blur import android.content.Context import android.os.Build import android.widget.FrameLayout import androidx.annotation.RequiresApi class BlurFrameLayout constructor(context: Context) : FrameLayout(context) { @RequiresApi(Build.VERSION_CODES.S) val blurController: SystemBlurController = SystemBlurController(this) } ================================================ FILE: app/src/main/java/com/zhenxiang/blur/BlurLinearLayout.kt ================================================ package com.zhenxiang.blur import android.content.Context import android.os.Build import android.widget.LinearLayout import androidx.annotation.RequiresApi class BlurLinearLayout constructor(context: Context) : LinearLayout(context) { @RequiresApi(Build.VERSION_CODES.S) val blurController: SystemBlurController = SystemBlurController(this) } ================================================ FILE: app/src/main/java/com/zhenxiang/blur/SystemBlurController.kt ================================================ package com.zhenxiang.blur import android.content.Context import android.graphics.Color import android.graphics.drawable.ShapeDrawable import android.graphics.drawable.shapes.RoundRectShape import android.os.Build import android.view.View import android.view.WindowManager import androidx.annotation.RequiresApi import com.android.internal.graphics.drawable.BackgroundBlurDrawable import com.sevtinge.cemiuiler.module.base.BaseHook.mPrefsMap import com.sevtinge.cemiuiler.utils.devicesdk.isMoreAndroidVersion import com.zhenxiang.blur.model.CornersRadius import java.util.function.Consumer @RequiresApi(Build.VERSION_CODES.S) class SystemBlurController( private val view: View, backgroundColour: Int = if (mPrefsMap.getInt("blur_view_color", -1) != -1) mPrefsMap.getInt("blur_view_color", -1) else Color.parseColor("#44FFFFFF"), blurRadius: Int = mPrefsMap.getInt("home_blur_radius", 100), cornerRadius: CornersRadius = CornersRadius.all(0f), ) : View.OnAttachStateChangeListener { private var windowManager: WindowManager? = null private val crossWindowBlurListener = Consumer { blurEnabled = it } private var blurEnabled: Boolean = false set(value) { if (value != field) { field = value updateBackgroundColour() updateBlurRadius() } } private var backgroundColour = backgroundColour set(value) { field = value updateBackgroundColour() } var blurRadius = blurRadius set(value) { field = value updateBlurRadius() } var cornerRadius = cornerRadius set(value) { field = value when (val bg = view.background) { is BackgroundBlurDrawable -> setCornerRadius(bg, value) is ShapeDrawable -> bg.shape = getShapeFromCorners(value) } } init { if (isMoreAndroidVersion(31)) { // On api 31 and above background init is done in onViewAttachedToWindow view.addOnAttachStateChangeListener(this) } else { // On pre api 31 init background here val shape = ShapeDrawable() shape.shape = getShapeFromCorners(cornerRadius) shape.paint.color = backgroundColour view.background = shape } } override fun onViewAttachedToWindow(v: View) { windowManager = getWindowManager(view.context).apply { blurEnabled = isCrossWindowBlurEnabled addCrossWindowBlurEnabledListener(crossWindowBlurListener) } view.createBackgroundBlurDrawable()?.let { // Configure blur drawable with current values it.setColor(backgroundColour) it.setBlurRadius(blurRadius) setCornerRadius(it, cornerRadius) view.background = it } } override fun onViewDetachedFromWindow(v: View) { // Clear blur drawable if (view.background is BackgroundBlurDrawable) { view.background = null } windowManager?.removeCrossWindowBlurEnabledListener(crossWindowBlurListener) windowManager = null } private fun updateBackgroundColour() { val bg = view.background when (bg) { is BackgroundBlurDrawable -> bg.setColor(backgroundColour) is ShapeDrawable -> bg.paint.color = backgroundColour } bg?.invalidateSelf() } private fun updateBlurRadius() { val bg = view.background if (bg is BackgroundBlurDrawable) { bg.setBlurRadius(if (blurEnabled) blurRadius else 0) } } private fun setCornerRadius(blurDrawable: BackgroundBlurDrawable, corners: CornersRadius) { blurDrawable.setCornerRadius( corners.topLeft, corners.topRight, corners.bottomLeft, corners.bottomRight ) } private fun getShapeFromCorners(corners: CornersRadius): RoundRectShape { return RoundRectShape(getCornersFloatArray(corners), null, null) } private fun getCornersFloatArray(corners: CornersRadius): FloatArray { return floatArrayOf( corners.topLeft, corners.topLeft, corners.topRight, corners.topRight, corners.bottomRight, corners.bottomRight, corners.bottomLeft, corners.bottomLeft ) } private fun getWindowManager(context: Context): WindowManager { return context.getSystemService(Context.WINDOW_SERVICE) as WindowManager } } ================================================ FILE: app/src/main/java/com/zhenxiang/blur/ViewExtensions.kt ================================================ package com.zhenxiang.blur import android.os.Build import android.util.Log import android.view.View import android.view.ViewRootImpl import androidx.annotation.RequiresApi import com.android.internal.graphics.drawable.BackgroundBlurDrawable import org.lsposed.hiddenapibypass.HiddenApiBypass @RequiresApi(Build.VERSION_CODES.S) fun View.createBackgroundBlurDrawable(): BackgroundBlurDrawable? { return try { val getViewRootImpl = HiddenApiBypass.invoke(View::class.java, this, "getViewRootImpl") as ViewRootImpl HiddenApiBypass.invoke( ViewRootImpl::class.java, getViewRootImpl, "createBackgroundBlurDrawable" ) as BackgroundBlurDrawable } catch (e: Exception) { Log.w(null, e) null } } ================================================ FILE: app/src/main/java/com/zhenxiang/blur/model/CornerRadius.kt ================================================ package com.zhenxiang.blur.model data class CornersRadius( val topLeft: Float, val topRight: Float, val bottomLeft: Float, val bottomRight: Float, ) { companion object { fun all(radius: Float): CornersRadius { return CornersRadius(radius, radius, radius, radius) } fun custom( topLeft: Float, topRight: Float, bottomLeft: Float, bottomRight: Float ): CornersRadius { return CornersRadius(topLeft, topRight, bottomLeft, bottomRight) } } } ================================================ FILE: app/src/main/res/color/ic_small_window_color.xml ================================================ ================================================ FILE: app/src/main/res/color/ic_small_window_color2.xml ================================================ ================================================ FILE: app/src/main/res/color/ic_small_window_color3.xml ================================================ ================================================ FILE: app/src/main/res/color/ic_small_window_color4.xml ================================================ ================================================ FILE: app/src/main/res/color/ic_small_window_color5.xml ================================================ ================================================ FILE: app/src/main/res/color/visual_check_text_color.xml ================================================ ================================================ FILE: app/src/main/res/drawable/baseline_wb_sunny_24.xml ================================================ ================================================ FILE: app/src/main/res/drawable/bubble_bar_pop_bg.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_android_settings.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_arrow_edit.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_ationbar_back.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_audio_system.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_cemiuiler_settings_v130.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_cemiuiler_settings_v140.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_control_center_5g_toggle_off.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_control_center_5g_toggle_on.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_control_center_gms_toggle_off.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_control_center_gms_toggle_on.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_default_icon.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_launcher_foreground.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_miui_volume_notification.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_miui_volume_notification_mute.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_packageinstaller_background_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_packageinstaller_background_light.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_qs_tile_bg_disabled.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_qs_tile_bg_enabled.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_qs_tile_bg_warning.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_reboot_small.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_settings.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_small_window.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_system_framework_new.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_system_ui_new.xml ================================================ ================================================ FILE: app/src/main/res/drawable/ic_various.xml ================================================ ================================================ FILE: app/src/main/res/drawable/shutdown_progress.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_0.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_0_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_0_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_0_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_0_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_0_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_1.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_1_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_1_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_1_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_1_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_1_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_2.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_2_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_2_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_2_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_2_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_2_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_3.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_3_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_3_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_3_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_3_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_3_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_4.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_4_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_4_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_4_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_4_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_4_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_5.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_5_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_5_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_5_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_5_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_1_5_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_0.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_0_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_0_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_0_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_0_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_0_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_1.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_1_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_1_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_1_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_1_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_1_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_2.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_2_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_2_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_2_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_2_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_2_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_3.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_3_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_3_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_3_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_3_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_3_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_4.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_4_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_4_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_4_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_4_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_4_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_5.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_5_dark.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_5_dark_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_5_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_5_tint.xml ================================================ ================================================ FILE: app/src/main/res/drawable/statusbar_signal_2_5_tint_thick.xml ================================================ ================================================ FILE: app/src/main/res/drawable-v31/ic_launcher_foreground.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_about.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_custom_hook.xml ================================================