diff --git a/app/build.gradle b/app/build.gradle index 4b393f4..6552efc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,8 +11,8 @@ android { applicationId "io.github.fplus" minSdk 24 targetSdk 33 - versionCode 111 - versionName "1.2.5-dev" + versionCode 112 + versionName "1.2.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { diff --git a/app/src/main/assets/version b/app/src/main/assets/version index b00d05d..7704187 100644 --- a/app/src/main/assets/version +++ b/app/src/main/assets/version @@ -1 +1 @@ -1.2.5-dev-111 \ No newline at end of file +1.2.5-112 \ No newline at end of file diff --git a/aweme/src/main/java/com/ss/android/ugc/aweme/feed/adapter/IFeedViewHolder.java b/aweme/src/main/java/com/ss/android/ugc/aweme/feed/adapter/IFeedViewHolder.java new file mode 100644 index 0000000..c96246e --- /dev/null +++ b/aweme/src/main/java/com/ss/android/ugc/aweme/feed/adapter/IFeedViewHolder.java @@ -0,0 +1,4 @@ +package com.ss.android.ugc.aweme.feed.adapter; + +public interface IFeedViewHolder { +} diff --git a/core/src/main/java/io/github/fplus/core/helper/DexkitBuilder.kt b/core/src/main/java/io/github/fplus/core/helper/DexkitBuilder.kt index d45c3e9..4c1c4c9 100644 --- a/core/src/main/java/io/github/fplus/core/helper/DexkitBuilder.kt +++ b/core/src/main/java/io/github/fplus/core/helper/DexkitBuilder.kt @@ -7,6 +7,7 @@ import com.freegang.ktutils.json.getIntOrDefault import com.freegang.ktutils.json.getJSONArrayOrDefault import com.freegang.ktutils.json.getStringOrDefault import com.freegang.ktutils.log.KLogCat +import com.freegang.ktutils.text.KTextUtils import io.github.fplus.core.config.ConfigV1 import io.github.xpler.core.findClass import io.github.xpler.core.findMethod @@ -41,12 +42,14 @@ object DexkitBuilder { var poiCreateInstanceImplClazz: Class<*>? = null var videoPlayerStateClazz: Class<*>? = null var videoPlayerHelperClazz: Class<*>? = null + var abstractFeedAdapterClazz: Class<*>? = null var recommendFeedFetchPresenterClazz: Class<*>? = null var fullFeedFollowFetchPresenterClazz: Class<*>? = null var detailPageFragmentClazz: Class<*>? = null var emojiApiProxyClazz: Class<*>? = null var emojiPopupWindowClazz: Class<*>? = null var ripsChatRoomFragmentClazz: Class<*>? = null + var restartUtilsClazz: Class<*>? = null // methods var videoViewHolderMethods: List = listOf() @@ -199,6 +202,32 @@ object DexkitBuilder { } }.singleInstance("conversationFragment") + abstractFeedAdapterClazz = bridge.findClass { + matcher { + fields { + add { + type = "android.view.LayoutInflater" + } + add { + type = "com.ss.android.ugc.aweme.feed.model.BaseFeedPageParams" + } + } + + methods { + add { + name = "getItemPosition" + } + add { + name = "finishUpdate" + } + } + + usingStrings { + add("AbstractFeedAdapter aweme.aid = ") + } + } + }.singleInstance("abstractFeedAdapter") + recommendFeedFetchPresenterClazz = bridge.findClass { matcher { methods { @@ -394,6 +423,21 @@ object DexkitBuilder { } }.singleInstance("mainBottomTabView") + restartUtilsClazz = bridge.findClass { + searchPackages("X") + matcher { + methods { + add { + paramTypes = listOf("android.content.Context") + usingNumbers = listOf(0x10008000) + } + } + usingStrings { + add("System.exit returned normally, while it was supposed to halt JVM.") + } + } + }.singleInstance("restartUtils") + val findMaps = bridge.batchFindClassUsingStrings { addSearchGroup { groupName = "videoPlayerHelper" @@ -504,12 +548,14 @@ object DexkitBuilder { poiCreateInstanceImplClazz = classCache.getStringOrDefault("poiCreateInstanceImpl").loadOrFindClass() videoPlayerStateClazz = classCache.getStringOrDefault("videoPlayerState").loadOrFindClass() videoPlayerHelperClazz = classCache.getStringOrDefault("videoPlayerHelper").loadOrFindClass() + abstractFeedAdapterClazz = classCache.getStringOrDefault("abstractFeedAdapter").loadOrFindClass() recommendFeedFetchPresenterClazz = classCache.getStringOrDefault("recommendFeedFetchPresenter").loadOrFindClass() fullFeedFollowFetchPresenterClazz = classCache.getStringOrDefault("fullFeedFollowFetchPresenter").loadOrFindClass() emojiPopupWindowClazz = classCache.getStringOrDefault("emojiPopupWindow").loadOrFindClass() detailPageFragmentClazz = classCache.getStringOrDefault("detailPageFragment").loadOrFindClass() emojiApiProxyClazz = classCache.getStringOrDefault("emojiApiProxy").loadOrFindClass() ripsChatRoomFragmentClazz = classCache.getStringOrDefault("ripsChatRoomFragment").loadOrFindClass() + restartUtilsClazz = classCache.getStringOrDefault("restartUtils").loadOrFindClass() } /** @@ -587,13 +633,17 @@ object DexkitBuilder { } private fun String.loadOrFindClass(): Class<*>? { - if (this.isEmpty()) { + if (KTextUtils.isEmpty(this)) { return null } return try { app?.classLoader?.loadClass(this) - } catch (e: ClassNotFoundException) { + } catch (e: Throwable) { + if (e is LinkageError && "${e.message}".contains("overrides final")) { + return null // 过滤类似错误 + } + lpparam.findClass(this) } } diff --git a/core/src/main/java/io/github/fplus/core/helper/ImmersiveHelper.kt b/core/src/main/java/io/github/fplus/core/helper/ImmersiveHelper.kt index d2eb414..2ddb9c1 100644 --- a/core/src/main/java/io/github/fplus/core/helper/ImmersiveHelper.kt +++ b/core/src/main/java/io/github/fplus/core/helper/ImmersiveHelper.kt @@ -4,49 +4,29 @@ import android.app.Activity import android.graphics.Color import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat -import com.freegang.ktutils.app.navBarInteractionMode object ImmersiveHelper { - @get:Synchronized - @set:Synchronized - var isEdgeToEdgeEnabled = false - - fun immersive(activity: Activity) { - val window = activity.window - if (activity.navBarInteractionMode == 2) { - ImmersiveHelper.isEdgeToEdgeEnabled = true - WindowCompat.setDecorFitsSystemWindows(window, false) - window.statusBarColor = Color.TRANSPARENT - window.navigationBarColor = Color.TRANSPARENT - } else { - window.statusBarColor = Color.TRANSPARENT - window.navigationBarColor = Color.parseColor("#161616") - } - } - - fun statusBar(activity: Activity, isHide: Boolean) { + fun immersive( + activity: Activity, + hideStatusBar: Boolean = false, + hideNavigationBars: Boolean = false, + ) { val window = activity.window WindowCompat.setDecorFitsSystemWindows(window, false) - window.statusBarColor = Color.TRANSPARENT WindowCompat.getInsetsController(window, window.decorView).apply { - if (isHide) { + if (hideStatusBar) { hide(WindowInsetsCompat.Type.statusBars()) } else { show(WindowInsetsCompat.Type.statusBars()) } - } - } - fun navigationBars(activity: Activity, isHide: Boolean) { - val window = activity.window - WindowCompat.setDecorFitsSystemWindows(window, false) - window.navigationBarColor = Color.TRANSPARENT - WindowCompat.getInsetsController(window, window.decorView).apply { - if (isHide) { + if (hideNavigationBars) { hide(WindowInsetsCompat.Type.navigationBars()) } else { show(WindowInsetsCompat.Type.navigationBars()) } } + window.statusBarColor = Color.TRANSPARENT + window.navigationBarColor = Color.TRANSPARENT } } \ No newline at end of file diff --git a/core/src/main/java/io/github/fplus/core/hook/DouYinMain.kt b/core/src/main/java/io/github/fplus/core/hook/DouYinMain.kt index 47e03f8..838b03a 100644 --- a/core/src/main/java/io/github/fplus/core/hook/DouYinMain.kt +++ b/core/src/main/java/io/github/fplus/core/hook/DouYinMain.kt @@ -71,7 +71,7 @@ class DouYinMain(private val app: Application) { // search and hook DexkitBuilder.running( app = app, - version = 3, + version = 4, searchBefore = { HActivity(lpparam) HMainActivity(lpparam) @@ -82,8 +82,6 @@ class DouYinMain(private val app: Application) { HFlippableViewPager(lpparam) HCustomizedUISeekBar(lpparam) HPlayerController(lpparam) - // HVideoViewHolder(lpparam) - HBaseCommonLiveViewHolder(lpparam) HVideoViewHolderRootView(lpparam) HPenetrateTouchRelativeLayout(lpparam) HInteractStickerParent(lpparam) @@ -105,7 +103,8 @@ class DouYinMain(private val app: Application) { HPoiCreateInstanceImpl(lpparam) HSeekBarSpeedModeBottomMask(lpparam) HVideoPlayerHelper(lpparam) - HVideoViewHolderV1(lpparam) + HVideoViewHolder(lpparam) + HAbstractFeedAdapter(lpparam) HVerticalViewPager(lpparam) HDetailPageFragment(lpparam) HEmojiDetailDialogNew(lpparam) diff --git a/core/src/main/java/io/github/fplus/core/hook/HBaseCommonLiveViewHolder.kt b/core/src/main/java/io/github/fplus/core/hook/HAbstractFeedAdapter.kt similarity index 67% rename from core/src/main/java/io/github/fplus/core/hook/HBaseCommonLiveViewHolder.kt rename to core/src/main/java/io/github/fplus/core/hook/HAbstractFeedAdapter.kt index 9a81dd3..2831a51 100644 --- a/core/src/main/java/io/github/fplus/core/hook/HBaseCommonLiveViewHolder.kt +++ b/core/src/main/java/io/github/fplus/core/hook/HAbstractFeedAdapter.kt @@ -9,36 +9,43 @@ import androidx.core.view.updatePadding import com.freegang.ktutils.display.dip2px import com.freegang.ktutils.extension.asOrNull import com.freegang.ktutils.log.KLogCat -import com.freegang.ktutils.reflect.fieldGets import com.freegang.ktutils.view.onEachChild +import com.ss.android.ugc.aweme.ad.feed.VideoViewHolderRootView import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.callbacks.XC_LoadPackage import io.github.fplus.core.base.BaseHook import io.github.fplus.core.config.ConfigV1 +import io.github.fplus.core.helper.DexkitBuilder +import io.github.xpler.core.NoneHook import io.github.xpler.core.OnAfter +import io.github.xpler.core.Param import io.github.xpler.core.hookBlockRunning -class HBaseCommonLiveViewHolder(lpparam: XC_LoadPackage.LoadPackageParam) : +class HAbstractFeedAdapter(lpparam: XC_LoadPackage.LoadPackageParam) : BaseHook(lpparam) { companion object { - const val TAG = "HBaseCommonLiveViewHolder" + const val TAG = "HAbstractFeedAdapter" } private val config get() = ConfigV1.get() override fun setTargetClass(): Class<*> { - return findClass("com.ss.android.ugc.aweme.feed.viewholder.BaseCommonLiveViewHolder") + return DexkitBuilder.abstractFeedAdapterClazz ?: NoneHook::class.java } - @OnAfter("bind") - fun bindAfter(params: XC_MethodHook.MethodHookParam) { + @OnAfter + fun methodAfter( + params: XC_MethodHook.MethodHookParam, + @Param("null") any: Any?, + view: View?, + i: Int, + ) { + // 垫高? hookBlockRunning(params) { if (config.isImmersive) { - val view = thisObject.fieldGets(type = View::class.java) - .firstOrNull() - // KLogCat.d("view: $view") - if (view is FrameLayout) { + view ?: return + if (view is FrameLayout && view !is VideoViewHolderRootView) { view.onEachChild { if (background is GradientDrawable) background = null } val bottomPadding = view.context.dip2px(58f) // BottomTabBarHeight val viewGroup = view.children.last().asOrNull() ?: return diff --git a/core/src/main/java/io/github/fplus/core/hook/HActivity.kt b/core/src/main/java/io/github/fplus/core/hook/HActivity.kt index 6752dac..89f5cfb 100644 --- a/core/src/main/java/io/github/fplus/core/hook/HActivity.kt +++ b/core/src/main/java/io/github/fplus/core/hook/HActivity.kt @@ -28,13 +28,11 @@ class HActivity(lpparam: XC_LoadPackage.LoadPackageParam) : DouYinMain.freeExitCountDown?.restart() if (event.action == MotionEvent.ACTION_DOWN) {// 重新沉浸 if (config.isImmersive) { - if (config.systemControllerValue[0]) { - ImmersiveHelper.statusBar(thisActivity, true) - } - if (config.systemControllerValue[1]) { - ImmersiveHelper.navigationBars(thisActivity, true) - } - ImmersiveHelper.immersive(thisActivity) + ImmersiveHelper.immersive( + thisActivity, + hideStatusBar = config.systemControllerValue[0], + hideNavigationBars = config.systemControllerValue[1], + ) } } }.onFailure { @@ -46,13 +44,11 @@ class HActivity(lpparam: XC_LoadPackage.LoadPackageParam) : fun onCreateAfter(params: XC_MethodHook.MethodHookParam, savedInstanceState: Bundle?) { hookBlockRunning(params) { if (config.isImmersive) { - if (config.systemControllerValue[0]) { - ImmersiveHelper.statusBar(thisActivity, true) - } - if (config.systemControllerValue[1]) { - ImmersiveHelper.navigationBars(thisActivity, true) - } - ImmersiveHelper.immersive(thisActivity) + ImmersiveHelper.immersive( + thisActivity, + hideStatusBar = config.systemControllerValue[0], + hideNavigationBars = config.systemControllerValue[1], + ) } }.onFailure { KLogCat.tagE(TAG, it) diff --git a/core/src/main/java/io/github/fplus/core/hook/HDetailActivity.kt b/core/src/main/java/io/github/fplus/core/hook/HDetailActivity.kt index 4fb286f..75e0e3f 100644 --- a/core/src/main/java/io/github/fplus/core/hook/HDetailActivity.kt +++ b/core/src/main/java/io/github/fplus/core/hook/HDetailActivity.kt @@ -68,7 +68,7 @@ class HDetailActivity(lpparam: XC_LoadPackage.LoadPackageParam) : DownloadLogic( this@HDetailActivity, activity, - aweme ?: HVideoViewHolderV1.aweme, + aweme ?: HVideoViewHolder.aweme, ) } } diff --git a/core/src/main/java/io/github/fplus/core/hook/HLivePlayActivity.kt b/core/src/main/java/io/github/fplus/core/hook/HLivePlayActivity.kt index 7d9882e..cf7bfe6 100644 --- a/core/src/main/java/io/github/fplus/core/hook/HLivePlayActivity.kt +++ b/core/src/main/java/io/github/fplus/core/hook/HLivePlayActivity.kt @@ -8,6 +8,7 @@ import io.github.fplus.core.config.ConfigV1 import io.github.fplus.core.helper.ImmersiveHelper import io.github.xpler.core.FutureHook import io.github.xpler.core.OnAfter +import io.github.xpler.core.OnBefore import io.github.xpler.core.hookBlockRunning import io.github.xpler.core.thisActivity @@ -25,13 +26,16 @@ class HLivePlayActivity(lpparam: XC_LoadPackage.LoadPackageParam) : } @FutureHook + @OnBefore("onWindowFocusChanged") @OnAfter("onWindowFocusChanged") fun onWindowFocusChangedAfter(params: XC_MethodHook.MethodHookParam, boolean: Boolean) { hookBlockRunning(params) { if (config.isImmersive) { - ImmersiveHelper.immersive(thisActivity) - // ImmersiveHelper.statusBar(thisActivity, true) - // ImmersiveHelper.navigationBars(thisActivity, true) + ImmersiveHelper.immersive( + thisActivity, + hideStatusBar = true, + hideNavigationBars = true, + ) } }.onFailure { KLogCat.tagE(TAG, it) diff --git a/core/src/main/java/io/github/fplus/core/hook/HMainActivity.kt b/core/src/main/java/io/github/fplus/core/hook/HMainActivity.kt index 0512f5d..9725c42 100644 --- a/core/src/main/java/io/github/fplus/core/hook/HMainActivity.kt +++ b/core/src/main/java/io/github/fplus/core/hook/HMainActivity.kt @@ -132,7 +132,7 @@ class HMainActivity(lpparam: XC_LoadPackage.LoadPackageParam) : DownloadLogic( this@HMainActivity, activity, - aweme ?: HVideoViewHolderV1.aweme, + aweme ?: HVideoViewHolder.aweme, ) } } diff --git a/core/src/main/java/io/github/fplus/core/hook/HSideBarNestedScrollView.kt b/core/src/main/java/io/github/fplus/core/hook/HSideBarNestedScrollView.kt index 8b34f18..983ba57 100644 --- a/core/src/main/java/io/github/fplus/core/hook/HSideBarNestedScrollView.kt +++ b/core/src/main/java/io/github/fplus/core/hook/HSideBarNestedScrollView.kt @@ -124,13 +124,6 @@ class HSideBarNestedScrollView(lpparam: XC_LoadPackage.LoadPackageParam) : view.context.startActivity(intent, options.toBundle()) } onlyChild.addView(binding.root) - - if (config.isImmersive) { - // 全面屏手势沉浸式底部垫高 (首页侧滑),底部导航栏则不处理 - if (ImmersiveHelper.isEdgeToEdgeEnabled) { - onlyChild.updatePadding(bottom = context.navigationBarHeight) - } - } } } } \ No newline at end of file diff --git a/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolder.kt b/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolder.kt index 2576d7a..ecd269d 100644 --- a/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolder.kt +++ b/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolder.kt @@ -1,13 +1,14 @@ package io.github.fplus.core.hook +import android.content.Context import android.view.View import android.view.ViewTreeObserver -import androidx.core.view.isVisible import com.freegang.ktutils.extension.asOrNull import com.freegang.ktutils.log.KLogCat import com.freegang.ktutils.reflect.fieldGetFirst import com.freegang.ktutils.reflect.fieldGets import com.freegang.ktutils.reflect.methodFirst +import com.freegang.ktutils.reflect.methodInvokeFirst import com.ss.android.ugc.aweme.feed.adapter.VideoViewHolder import com.ss.android.ugc.aweme.feed.model.Aweme import com.ss.android.ugc.aweme.feed.ui.PenetrateTouchRelativeLayout @@ -16,13 +17,16 @@ import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.callbacks.XC_LoadPackage import io.github.fplus.core.base.BaseHook import io.github.fplus.core.config.ConfigV1 +import io.github.fplus.core.helper.DexkitBuilder import io.github.xpler.core.OnAfter import io.github.xpler.core.OnBefore +import io.github.xpler.core.hook import io.github.xpler.core.hookBlockRunning +import io.github.xpler.core.interfaces.CallConstructors -@Deprecated("暂存区") class HVideoViewHolder(lpparam: XC_LoadPackage.LoadPackageParam) : - BaseHook(lpparam) { + BaseHook(lpparam), CallConstructors { + companion object { const val TAG = "HVideoViewHolder" @@ -31,12 +35,10 @@ class HVideoViewHolder(lpparam: XC_LoadPackage.LoadPackageParam) : var aweme: Aweme? = null } - private var isClearMode = false + private val config get() = ConfigV1.get() private var onDrawMaps = mutableMapOf() - private val config get() = ConfigV1.get() - private fun addOnDraw(view: View?) { if (view == null) { KLogCat.d("addOnDraw", "view == null") @@ -52,18 +54,6 @@ class HVideoViewHolder(lpparam: XC_LoadPackage.LoadPackageParam) : view.alpha = alpha } } - - if (config.isNeatMode) { - if (config.neatModeState) { - if (!HPlayerController.isPlaying && isClearMode) { - view.isVisible = false - HMainActivity.toggleView(false) - } else { - view.isVisible = !HPlayerController.isPlaying - HMainActivity.toggleView(!HPlayerController.isPlaying) - } - } - } }) view.viewTreeObserver.addOnDrawListener(onDrawMaps[key]) @@ -94,18 +84,51 @@ class HVideoViewHolder(lpparam: XC_LoadPackage.LoadPackageParam) : KLogCat.d("监听集合", *first.map { "$it" }.toTypedArray()) } + private fun callOpenCleanMode(params: XC_MethodHook.MethodHookParam, bool: Boolean) { + if (!config.isNeatMode) { + return + } + + if (!config.neatModeState) { + return + } + + val first = params.thisObject.methodFirst("openCleanMode", paramTypes = arrayOf(Boolean::class.java)) + XposedBridge.invokeOriginalMethod(first, params.thisObject, arrayOf(bool)) + + // + HMainActivity.toggleView(!bool) + } + + private fun getAllView(params: XC_MethodHook.MethodHookParam): List { + val views = params.thisObject.fieldGets(type = View::class.java) + return views.asOrNull>() ?: emptyList() + } + + private fun getWidgetContainer(params: XC_MethodHook.MethodHookParam): PenetrateTouchRelativeLayout? { + val views = params.thisObject?.fieldGets(type = View::class.java) ?: emptyList() + return views.firstOrNull { it is PenetrateTouchRelativeLayout } + ?.asOrNull() + } + + private fun getContext(params: XC_MethodHook.MethodHookParam): Context? { + return params.thisObject.methodInvokeFirst("getContext")?.asOrNull() + } + @OnAfter("getAweme") fun getAwemeAfter(params: XC_MethodHook.MethodHookParam) { hookBlockRunning(params) { - aweme = result.asOrNull() + HVideoViewHolder.aweme = result.asOrNull() }.onFailure { - KLogCat.tagE(TAG, it) + KLogCat.tagE(HVideoViewHolder.TAG, it) } } @OnAfter("onViewHolderSelected") fun onViewHolderSelectedAfter(params: XC_MethodHook.MethodHookParam, index: Int) { hookBlockRunning(params) { + // KLogCat.d("onViewHolderSelected") + callOpenCleanMode(params, true) val container = getWidgetContainer(params) addOnDraw(container) }.onFailure { @@ -116,6 +139,7 @@ class HVideoViewHolder(lpparam: XC_LoadPackage.LoadPackageParam) : @OnAfter("onViewHolderUnSelected") fun onViewHolderUnSelectedAfter(params: XC_MethodHook.MethodHookParam) { hookBlockRunning(params) { + // KLogCat.d("onViewHolderSelected") val container = getWidgetContainer(params) removeOnDraw(container) }.onFailure { @@ -144,28 +168,21 @@ class HVideoViewHolder(lpparam: XC_LoadPackage.LoadPackageParam) : } } - @OnBefore - fun booleanAllBefore(params: XC_MethodHook.MethodHookParam, boolean: Boolean) { - hookBlockRunning(params) { - // KLogCat.d("$method", "$boolean") - isClearMode = if (HPlayerController.isPlaying) { - false - } else { - boolean - } - }.onFailure { - KLogCat.tagE(TAG, it) - } + override fun callOnBeforeConstructors(params: XC_MethodHook.MethodHookParam) { + } - private fun getWidgetContainer(params: XC_MethodHook.MethodHookParam): PenetrateTouchRelativeLayout? { - val views = params.thisObject?.fieldGets(type = View::class.java) ?: emptyList() - return views.firstOrNull { it is PenetrateTouchRelativeLayout } - ?.asOrNull() + override fun callOnAfterConstructors(params: XC_MethodHook.MethodHookParam) { + hookBlockRunning(params) { + callOpenCleanMode(params, true) + } } - private fun callOpenCleanMode(params: XC_MethodHook.MethodHookParam, boolean: Boolean) { - val first = params.thisObject.methodFirst("openCleanMode", paramTypes = arrayOf(Boolean::class.java)) - XposedBridge.invokeOriginalMethod(first, params.thisObject, arrayOf(boolean)) + override fun onInit() { + DexkitBuilder.videoViewHolderMethods.firstOrNull()?.hook { + onAfter { + callOpenCleanMode(this, true) + } + } } } \ No newline at end of file diff --git a/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolderRootView.kt b/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolderRootView.kt index 3bdffe5..53d2557 100644 --- a/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolderRootView.kt +++ b/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolderRootView.kt @@ -237,7 +237,7 @@ class HVideoViewHolderRootView(lpparam: XC_LoadPackage.LoadPackageParam) : DownloadLogic( this@HVideoViewHolderRootView, view.context, - HVideoViewHolderV1.aweme, + HVideoViewHolder.aweme, ) } @@ -386,7 +386,7 @@ class HVideoViewHolderRootView(lpparam: XC_LoadPackage.LoadPackageParam) : DownloadLogic( this@HVideoViewHolderRootView, view.context, - HVideoViewHolderV1.aweme, + HVideoViewHolder.aweme, ) } diff --git a/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolderV1.kt b/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolderV1.kt deleted file mode 100644 index 9bdc61b..0000000 --- a/core/src/main/java/io/github/fplus/core/hook/HVideoViewHolderV1.kt +++ /dev/null @@ -1,182 +0,0 @@ -package io.github.fplus.core.hook - -import android.view.View -import android.view.ViewTreeObserver -import com.freegang.ktutils.extension.asOrNull -import com.freegang.ktutils.log.KLogCat -import com.freegang.ktutils.reflect.fieldGetFirst -import com.freegang.ktutils.reflect.fieldGets -import com.freegang.ktutils.reflect.methodFirst -import com.ss.android.ugc.aweme.feed.adapter.VideoViewHolder -import com.ss.android.ugc.aweme.feed.model.Aweme -import com.ss.android.ugc.aweme.feed.ui.PenetrateTouchRelativeLayout -import de.robv.android.xposed.XC_MethodHook -import de.robv.android.xposed.XposedBridge -import de.robv.android.xposed.callbacks.XC_LoadPackage -import io.github.fplus.core.base.BaseHook -import io.github.fplus.core.config.ConfigV1 -import io.github.fplus.core.helper.DexkitBuilder -import io.github.xpler.core.OnAfter -import io.github.xpler.core.OnBefore -import io.github.xpler.core.hook -import io.github.xpler.core.hookBlockRunning -import io.github.xpler.core.interfaces.CallConstructors - -class HVideoViewHolderV1(lpparam: XC_LoadPackage.LoadPackageParam) : - BaseHook(lpparam), CallConstructors { - - companion object { - const val TAG = "HVideoViewHolder" - - @get:Synchronized - @set:Synchronized - var aweme: Aweme? = null - } - - private val config get() = ConfigV1.get() - - private var onDrawMaps = mutableMapOf() - - private fun addOnDraw(view: View?) { - if (view == null) { - KLogCat.d("addOnDraw", "view == null") - return - } - - val key = Integer.toHexString(System.identityHashCode(view)) - - onDrawMaps.putIfAbsent(key, ViewTreeObserver.OnDrawListener { - if (config.isTranslucent) { - val alpha = config.translucentValue[1] / 100f - if (view.alpha > alpha) { - view.alpha = alpha - } - } - }) - - view.viewTreeObserver.addOnDrawListener(onDrawMaps[key]) - } - - private fun removeOnDraw(view: View?) { - if (view == null) { - KLogCat.d("removeOnDraw", "view == null") - return - } - - val key = Integer.toHexString(System.identityHashCode(view)) - view.viewTreeObserver.removeOnDrawListener(onDrawMaps[key]) - } - - private fun testOnDraw(tag: String) { - val array = onDrawMaps.map { "${it.key} = ${it.value}" }.toTypedArray() - KLogCat.d(tag, *array) - } - - private fun testAllOnDraw(view: View?) { - if (view == null) { - KLogCat.d("removeOnDraw", "view == null") - return - } - - val first = view.viewTreeObserver.fieldGetFirst("mOnDrawListeners")?.asOrNull>() ?: return - KLogCat.d("监听集合", *first.map { "$it" }.toTypedArray()) - } - - private fun callOpenCleanMode(params: XC_MethodHook.MethodHookParam, bool: Boolean) { - if (!config.isNeatMode) { - return - } - - if (!config.neatModeState) { - return - } - - val first = params.thisObject.methodFirst("openCleanMode", paramTypes = arrayOf(Boolean::class.java)) - XposedBridge.invokeOriginalMethod(first, params.thisObject, arrayOf(bool)) - - // - HMainActivity.toggleView(!bool) - } - - private fun getAllView(params: XC_MethodHook.MethodHookParam): List { - val views = params.thisObject.fieldGets(type = View::class.java) - return views.asOrNull>() ?: emptyList() - } - - private fun getWidgetContainer(params: XC_MethodHook.MethodHookParam): PenetrateTouchRelativeLayout? { - val views = params.thisObject?.fieldGets(type = View::class.java) ?: emptyList() - return views.firstOrNull { it is PenetrateTouchRelativeLayout } - ?.asOrNull() - } - - @OnAfter("getAweme") - fun getAwemeAfter(params: XC_MethodHook.MethodHookParam) { - hookBlockRunning(params) { - HVideoViewHolderV1.aweme = result.asOrNull() - }.onFailure { - KLogCat.tagE(HVideoViewHolderV1.TAG, it) - } - } - - @OnAfter("onViewHolderSelected") - fun onViewHolderSelectedAfter(params: XC_MethodHook.MethodHookParam, index: Int) { - hookBlockRunning(params) { - // KLogCat.d("onViewHolderSelected") - callOpenCleanMode(params, true) - val container = getWidgetContainer(params) - addOnDraw(container) - }.onFailure { - KLogCat.tagE(TAG, it) - } - } - - @OnAfter("onViewHolderUnSelected") - fun onViewHolderUnSelectedAfter(params: XC_MethodHook.MethodHookParam) { - hookBlockRunning(params) { - // KLogCat.d("onViewHolderSelected") - val container = getWidgetContainer(params) - removeOnDraw(container) - }.onFailure { - KLogCat.tagE(TAG, it) - } - } - - @OnBefore("onPause") - fun onPauseBefore(params: XC_MethodHook.MethodHookParam) { - hookBlockRunning(params) { - val container = getWidgetContainer(params) - removeOnDraw(container) - onDrawMaps.clear() - }.onFailure { - KLogCat.tagE(TAG, it) - } - } - - @OnAfter("onResume") - fun onResumeAfter(params: XC_MethodHook.MethodHookParam) { - hookBlockRunning(params) { - val container = getWidgetContainer(params) - addOnDraw(container) - }.onFailure { - KLogCat.tagE(TAG, it) - } - } - - override fun callOnBeforeConstructors(params: XC_MethodHook.MethodHookParam) { - - } - - override fun callOnAfterConstructors(params: XC_MethodHook.MethodHookParam) { - hookBlockRunning(params) { - callOpenCleanMode(params, true) - } - } - - override fun onInit() { - DexkitBuilder.videoViewHolderMethods.firstOrNull()?.hook { - onAfter { - callOpenCleanMode(this, true) - } - } - } -} \ No newline at end of file diff --git a/core/src/main/java/io/github/fplus/core/ui/activity/FreedomSettingActivity.kt b/core/src/main/java/io/github/fplus/core/ui/activity/FreedomSettingActivity.kt index a54392a..6f280c3 100644 --- a/core/src/main/java/io/github/fplus/core/ui/activity/FreedomSettingActivity.kt +++ b/core/src/main/java/io/github/fplus/core/ui/activity/FreedomSettingActivity.kt @@ -59,9 +59,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope -import com.freegang.ktutils.app.KAppUtils import com.freegang.ktutils.app.KToastUtils +import com.freegang.ktutils.reflect.methodInvokeFirst import io.github.fplus.core.R +import io.github.fplus.core.helper.DexkitBuilder import io.github.fplus.core.helper.HighlightStyleBuilder import io.github.fplus.core.ui.ModuleTheme import io.github.fplus.core.ui.asDp @@ -155,6 +156,7 @@ class FreedomSettingActivity : XplerActivity() { } Icon( painter = painterResource(id = R.drawable.ic_manage), + // imageVector = Icons.Rounded.Search, contentDescription = "Log", modifier = Modifier .size(24.dp) @@ -214,6 +216,7 @@ class FreedomSettingActivity : XplerActivity() { Icon( painter = painterResource(id = R.drawable.ic_motion), + // imageVector = Icons.Rounded.Info, contentDescription = "更新日志", modifier = Modifier .size(20.dp) @@ -276,7 +279,8 @@ class FreedomSettingActivity : XplerActivity() { }.onFailure { model.setVersionConfig(null) } - KAppUtils.restartApplication(application) + // KAppUtils.restartApplication(application) + DexkitBuilder.restartUtilsClazz?.methodInvokeFirst(args = arrayOf(this)) }, ) { Text( diff --git a/core/src/main/java/io/github/fplus/core/ui/compat/XplerCompat.kt b/core/src/main/java/io/github/fplus/core/ui/compat/XplerCompat.kt index 8d7cc87..6bc5eae 100644 --- a/core/src/main/java/io/github/fplus/core/ui/compat/XplerCompat.kt +++ b/core/src/main/java/io/github/fplus/core/ui/compat/XplerCompat.kt @@ -45,7 +45,7 @@ fun painterResourceCompat(@DrawableRes id: Int): Painter { * Helper method to seek to the first tag within the VectorDrawable xml asset */ @Throws(XmlPullParserException::class) -fun XmlPullParser.seekToStartTag(): XmlPullParser { +private fun XmlPullParser.seekToStartTag(): XmlPullParser { var type = next() while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { // Empty loop diff --git a/core/src/main/java/io/github/fplus/plugin/PluginContextThemeWrapper.kt b/core/src/main/java/io/github/fplus/plugin/PluginContextThemeWrapper.kt index 912e051..49da187 100644 --- a/core/src/main/java/io/github/fplus/plugin/PluginContextThemeWrapper.kt +++ b/core/src/main/java/io/github/fplus/plugin/PluginContextThemeWrapper.kt @@ -41,8 +41,11 @@ class PluginContextThemeWrapper( } override fun getAssets(): AssetManager { - // return mResources.assets - return mResources.pluginAssets + val resources = mResources + if (resources is PluginResources?) { + return resources?.pluginAssets ?: mResources?.assets ?: super.getAssets() + } + return resources?.assets ?: super.getAssets() } override fun getTheme(): Resources.Theme { diff --git a/core/src/main/java/io/github/fplus/plugin/PluginResources.kt b/core/src/main/java/io/github/fplus/plugin/PluginResources.kt index 908a842..ba082c8 100644 --- a/core/src/main/java/io/github/fplus/plugin/PluginResources.kt +++ b/core/src/main/java/io/github/fplus/plugin/PluginResources.kt @@ -46,7 +46,7 @@ class PluginResources( val pluginAssets: AssetManager get() = pluginResources.assets override fun getText(id: Int): CharSequence { - return try { + /*return try { originResources.getText(id) } catch (e: Exception) { try { @@ -54,11 +54,21 @@ class PluginResources( } catch (e: Exception) { "Unknown" } + }*/ + + return try { + pluginResources.getText(id) + } catch (e: Exception) { + try { + originResources.getText(id) + } catch (e: Exception) { + "Unknown" + } } } override fun getText(id: Int, def: CharSequence?): CharSequence { - return try { + /*return try { originResources.getText(id, def) } catch (e: Exception) { try { @@ -66,20 +76,36 @@ class PluginResources( } catch (e: Exception) { "Unknown" } + }*/ + + return try { + pluginResources.getText(id, def) + } catch (e: Exception) { + try { + originResources.getText(id, def) + } catch (e: Exception) { + "Unknown" + } } } @SuppressLint("NewApi") override fun getFont(id: Int): Typeface { - return try { + /*return try { originResources.getFont(id) } catch (e: Exception) { pluginResources.getFont(id) + }*/ + + return try { + pluginResources.getFont(id) + } catch (e: Exception) { + originResources.getFont(id) } } override fun getQuantityText(id: Int, quantity: Int): CharSequence { - return try { + /*return try { originResources.getQuantityText(id, quantity) } catch (e: Exception) { try { @@ -87,11 +113,21 @@ class PluginResources( } catch (e: Exception) { "Unknown" } + }*/ + + return try { + pluginResources.getQuantityText(id, quantity) + } catch (e: Exception) { + try { + originResources.getQuantityText(id, quantity) + } catch (e: Exception) { + "Unknown" + } } } override fun getString(id: Int): String { - return try { + /*return try { originResources.getString(id) } catch (e: Exception) { try { @@ -99,11 +135,21 @@ class PluginResources( } catch (e: Exception) { "Unknown" } + }*/ + + return try { + pluginResources.getString(id) + } catch (e: Exception) { + try { + originResources.getString(id) + } catch (e: Exception) { + "Unknown" + } } } override fun getString(id: Int, vararg formatArgs: Any?): String { - return try { + /*return try { originResources.getString(id, *formatArgs) } catch (e: Exception) { try { @@ -111,11 +157,21 @@ class PluginResources( } catch (e: Exception) { "Unknown" } + }*/ + + return try { + pluginResources.getString(id, *formatArgs) + } catch (e: Exception) { + try { + originResources.getString(id, *formatArgs) + } catch (e: Exception) { + "Unknown" + } } } override fun getQuantityString(id: Int, quantity: Int, vararg formatArgs: Any?): String { - return try { + /*return try { originResources.getQuantityString(id, quantity, *formatArgs) } catch (e: Exception) { try { @@ -123,15 +179,25 @@ class PluginResources( } catch (e: Exception) { "Unknown" } + }*/ + + return try { + pluginResources.getQuantityString(id, quantity, *formatArgs) + } catch (e: Exception) { + try { + originResources.getQuantityString(id, quantity, *formatArgs) + } catch (e: Exception) { + "Unknown" + } } } override fun getQuantityString(id: Int, quantity: Int): String { return try { - originResources.getQuantityString(id, quantity) + pluginResources.getQuantityString(id, quantity) } catch (e: Exception) { try { - pluginResources.getQuantityString(id, quantity) + originResources.getQuantityString(id, quantity) } catch (e: Exception) { "Unknown" } @@ -139,187 +205,319 @@ class PluginResources( } override fun getTextArray(id: Int): Array { - return try { + /*return try { originResources.getTextArray(id) } catch (e: Exception) { pluginResources.getTextArray(id) + }*/ + + return try { + pluginResources.getTextArray(id) + } catch (e: Exception) { + originResources.getTextArray(id) } } override fun getStringArray(id: Int): Array { - return try { + /*return try { originResources.getStringArray(id) } catch (e: Exception) { pluginResources.getStringArray(id) + }*/ + + return try { + pluginResources.getStringArray(id) + } catch (e: Exception) { + originResources.getStringArray(id) } } override fun getIntArray(id: Int): IntArray { - return try { + /*return try { originResources.getIntArray(id) } catch (e: Exception) { pluginResources.getIntArray(id) + }*/ + + return try { + pluginResources.getIntArray(id) + } catch (e: Exception) { + originResources.getIntArray(id) } } override fun obtainTypedArray(id: Int): TypedArray { - return try { + /*return try { originResources.obtainTypedArray(id) } catch (e: Exception) { pluginResources.obtainTypedArray(id) + }*/ + + return try { + pluginResources.obtainTypedArray(id) + } catch (e: Exception) { + originResources.obtainTypedArray(id) } } override fun getDimension(id: Int): Float { - return try { + /*return try { originResources.getDimension(id) } catch (e: Exception) { pluginResources.getDimension(id) + }*/ + + return try { + pluginResources.getDimension(id) + } catch (e: Exception) { + originResources.getDimension(id) } } override fun getDimensionPixelOffset(id: Int): Int { - return try { + /*return try { originResources.getDimensionPixelOffset(id) } catch (e: Exception) { pluginResources.getDimensionPixelOffset(id) + }*/ + + return try { + pluginResources.getDimensionPixelOffset(id) + } catch (e: Exception) { + originResources.getDimensionPixelOffset(id) } } override fun getDimensionPixelSize(id: Int): Int { - return try { + /*return try { originResources.getDimensionPixelSize(id) } catch (e: Exception) { pluginResources.getDimensionPixelSize(id) + }*/ + + return try { + pluginResources.getDimensionPixelSize(id) + } catch (e: Exception) { + originResources.getDimensionPixelSize(id) } } override fun getFraction(id: Int, base: Int, pbase: Int): Float { + /* return try { + originResources.getFraction(id, base, pbase) + } catch (e: Exception) { + pluginResources.getFraction(id, base, pbase) + }*/ + return try { - originResources.getFraction(id, base, pbase) - } catch (e: Exception) { pluginResources.getFraction(id, base, pbase) + } catch (e: Exception) { + originResources.getFraction(id, base, pbase) } } @Deprecated("Deprecated in Java") @SuppressLint("UseCompatLoadingForDrawables") override fun getDrawable(id: Int): Drawable { - return try { + /*return try { originResources.getDrawable(id) } catch (e: Exception) { pluginResources.getDrawable(id) + }*/ + + return try { + pluginResources.getDrawable(id) + } catch (e: Exception) { + originResources.getDrawable(id) } } @SuppressLint("UseCompatLoadingForDrawables") override fun getDrawable(id: Int, theme: Theme?): Drawable { - return try { + /*return try { originResources.getDrawable(id, theme) } catch (e: Exception) { pluginResources.getDrawable(id, theme) + }*/ + + return try { + pluginResources.getDrawable(id, theme) + } catch (e: Exception) { + originResources.getDrawable(id, theme) } } @Deprecated("Deprecated in Java") override fun getDrawableForDensity(id: Int, density: Int): Drawable? { - return try { + /*return try { originResources.getDrawableForDensity(id, density) } catch (e: Exception) { pluginResources.getDrawableForDensity(id, density) + }*/ + + return try { + pluginResources.getDrawableForDensity(id, density) + } catch (e: Exception) { + originResources.getDrawableForDensity(id, density) } } override fun getDrawableForDensity(id: Int, density: Int, theme: Theme?): Drawable? { - return try { + /*return try { originResources.getDrawableForDensity(id, density, theme) } catch (e: Exception) { pluginResources.getDrawableForDensity(id, density, theme) + }*/ + + return try { + pluginResources.getDrawableForDensity(id, density, theme) + } catch (e: Exception) { + originResources.getDrawableForDensity(id, density, theme) } } @Deprecated("Deprecated in Java") override fun getMovie(id: Int): Movie { - return try { + /*return try { originResources.getMovie(id) } catch (e: Exception) { pluginResources.getMovie(id) + }*/ + + return try { + pluginResources.getMovie(id) + } catch (e: Exception) { + originResources.getMovie(id) } } @Deprecated("Deprecated in Java") override fun getColor(id: Int): Int { - return try { + /*return try { originResources.getColor(id) } catch (e: Exception) { pluginResources.getColor(id) + }*/ + + return try { + pluginResources.getColor(id) + } catch (e: Exception) { + originResources.getColor(id) } } override fun getColor(id: Int, theme: Theme?): Int { - return try { + /*return try { originResources.getColor(id, theme) } catch (e: Exception) { pluginResources.getColor(id, theme) + }*/ + + return try { + pluginResources.getColor(id, theme) + } catch (e: Exception) { + originResources.getColor(id, theme) } } @SuppressLint("UseCompatLoadingForColorStateLists") @Deprecated("Deprecated in Java") override fun getColorStateList(id: Int): ColorStateList { - return try { + /*return try { originResources.getColorStateList(id) } catch (e: Exception) { pluginResources.getColorStateList(id) + }*/ + + return try { + pluginResources.getColorStateList(id) + } catch (e: Exception) { + originResources.getColorStateList(id) } } override fun getColorStateList(id: Int, theme: Theme?): ColorStateList { - return try { + /*return try { originResources.getColorStateList(id, theme) } catch (e: Exception) { pluginResources.getColorStateList(id, theme) + }*/ + + return try { + pluginResources.getColorStateList(id, theme) + } catch (e: Exception) { + originResources.getColorStateList(id, theme) } } override fun getBoolean(id: Int): Boolean { - return try { + /*return try { originResources.getBoolean(id) } catch (e: Exception) { pluginResources.getBoolean(id) + }*/ + + return try { + pluginResources.getBoolean(id) + } catch (e: Exception) { + originResources.getBoolean(id) } } override fun getInteger(id: Int): Int { - return try { + /*return try { originResources.getInteger(id) } catch (e: Exception) { pluginResources.getInteger(id) + }*/ + + return try { + pluginResources.getInteger(id) + } catch (e: Exception) { + originResources.getInteger(id) } } @SuppressLint("NewApi") override fun getFloat(id: Int): Float { - return try { + /*return try { originResources.getFloat(id) } catch (e: Exception) { pluginResources.getFloat(id) + }*/ + + return try { + pluginResources.getFloat(id) + } catch (e: Exception) { + originResources.getFloat(id) } } override fun getLayout(id: Int): XmlResourceParser { - return try { + /*return try { originResources.getLayout(id) } catch (e: Exception) { pluginResources.getLayout(id) + }*/ + + return try { + pluginResources.getLayout(id) + } catch (e: Exception) { + originResources.getLayout(id) } } override fun getAnimation(id: Int): XmlResourceParser { - return try { + /*return try { originResources.getAnimation(id) } catch (e: Exception) { pluginResources.getAnimation(id) + }*/ + + return try { + pluginResources.getAnimation(id) + } catch (e: Exception) { + originResources.getAnimation(id) } } @@ -338,159 +536,273 @@ class PluginResources( } override fun openRawResource(id: Int): InputStream { - return try { + /*return try { originResources.openRawResource(id) } catch (e: Exception) { pluginResources.openRawResource(id) + }*/ + + return try { + pluginResources.openRawResource(id) + } catch (e: Exception) { + originResources.openRawResource(id) } } override fun openRawResource(id: Int, value: TypedValue?): InputStream { - return try { + /*return try { originResources.openRawResource(id, value) } catch (e: Exception) { pluginResources.openRawResource(id, value) + }*/ + + return try { + pluginResources.openRawResource(id, value) + } catch (e: Exception) { + originResources.openRawResource(id, value) } } override fun openRawResourceFd(id: Int): AssetFileDescriptor { - return try { + /*return try { originResources.openRawResourceFd(id) } catch (e: Exception) { pluginResources.openRawResourceFd(id) + }*/ + + return try { + pluginResources.openRawResourceFd(id) + } catch (e: Exception) { + originResources.openRawResourceFd(id) } } override fun getValue(id: Int, outValue: TypedValue?, resolveRefs: Boolean) { - try { + /*try { originResources.getValue(id, outValue, resolveRefs) } catch (e: Exception) { pluginResources.getValue(id, outValue, resolveRefs) + }*/ + + try { + pluginResources.getValue(id, outValue, resolveRefs) + } catch (e: Exception) { + originResources.getValue(id, outValue, resolveRefs) } } @SuppressLint("DiscouragedApi") override fun getValue(name: String?, outValue: TypedValue?, resolveRefs: Boolean) { - try { + /*try { originResources.getValue(name, outValue, resolveRefs) } catch (e: Exception) { pluginResources.getValue(name, outValue, resolveRefs) + }*/ + + try { + pluginResources.getValue(name, outValue, resolveRefs) + } catch (e: Exception) { + originResources.getValue(name, outValue, resolveRefs) } } override fun getValueForDensity(id: Int, density: Int, outValue: TypedValue?, resolveRefs: Boolean) { - try { + /*try { originResources.getValueForDensity(id, density, outValue, resolveRefs) } catch (e: Exception) { pluginResources.getValueForDensity(id, density, outValue, resolveRefs) + }*/ + + try { + pluginResources.getValueForDensity(id, density, outValue, resolveRefs) + } catch (e: Exception) { + originResources.getValueForDensity(id, density, outValue, resolveRefs) } } override fun obtainAttributes(set: AttributeSet?, attrs: IntArray?): TypedArray { - return try { + /*return try { originResources.obtainAttributes(set, attrs) } catch (e: Exception) { pluginResources.obtainAttributes(set, attrs) + }*/ + + return try { + pluginResources.obtainAttributes(set, attrs) + } catch (e: Exception) { + originResources.obtainAttributes(set, attrs) } } @Deprecated("Deprecated in Java") override fun updateConfiguration(config: Configuration?, metrics: DisplayMetrics?) { - try { + /*try { originResources.updateConfiguration(config, metrics) } catch (e: Exception) { pluginResources.updateConfiguration(config, metrics) + }*/ + + try { + pluginResources.updateConfiguration(config, metrics) + } catch (e: Exception) { + originResources.updateConfiguration(config, metrics) } } override fun getDisplayMetrics(): DisplayMetrics { - return try { + /*return try { originResources.displayMetrics } catch (e: Exception) { pluginResources.displayMetrics + }*/ + + return try { + pluginResources.displayMetrics + } catch (e: Exception) { + originResources.displayMetrics } } override fun getConfiguration(): Configuration { + /*return try { + originResources.configuration + } catch (e: Exception) { + pluginResources.configuration + }*/ + return try { - originResources.getConfiguration() + pluginResources.configuration } catch (e: Exception) { - pluginResources.getConfiguration() + originResources.configuration } } @SuppressLint("DiscouragedApi") override fun getIdentifier(name: String?, defType: String?, defPackage: String?): Int { - return try { + /*return try { originResources.getIdentifier(name, defType, defPackage) } catch (e: Exception) { pluginResources.getIdentifier(name, defType, defPackage) + }*/ + + return try { + pluginResources.getIdentifier(name, defType, defPackage) + } catch (e: Exception) { + originResources.getIdentifier(name, defType, defPackage) } } override fun getResourceName(resid: Int): String { - return return try { + /*return try { originResources.getResourceName(resid) } catch (e: Exception) { pluginResources.getResourceName(resid) + }*/ + + return try { + pluginResources.getResourceName(resid) + } catch (e: Exception) { + originResources.getResourceName(resid) } } override fun getResourcePackageName(resid: Int): String { - return try { + /*return try { originResources.getResourcePackageName(resid) } catch (e: Exception) { pluginResources.getResourcePackageName(resid) + }*/ + + return try { + pluginResources.getResourcePackageName(resid) + } catch (e: Exception) { + originResources.getResourcePackageName(resid) } } override fun getResourceTypeName(resid: Int): String { + /* return try { + originResources.getResourceTypeName(resid) + } catch (e: Exception) { + pluginResources.getResourceTypeName(resid) + }*/ + return try { - originResources.getResourceTypeName(resid) - } catch (e: Exception) { pluginResources.getResourceTypeName(resid) + } catch (e: Exception) { + originResources.getResourceTypeName(resid) } } override fun getResourceEntryName(resid: Int): String { - return try { + /*return try { originResources.getResourceEntryName(resid) } catch (e: Exception) { pluginResources.getResourceEntryName(resid) + }*/ + + return try { + pluginResources.getResourceEntryName(resid) + } catch (e: Exception) { + originResources.getResourceEntryName(resid) } } override fun parseBundleExtras(parser: XmlResourceParser?, outBundle: Bundle?) { - try { + /*try { originResources.parseBundleExtras(parser, outBundle) } catch (e: Exception) { pluginResources.parseBundleExtras(parser, outBundle) + }*/ + + try { + pluginResources.parseBundleExtras(parser, outBundle) + } catch (e: Exception) { + originResources.parseBundleExtras(parser, outBundle) } } override fun parseBundleExtra(tagName: String?, attrs: AttributeSet?, outBundle: Bundle?) { + /* try { + originResources.parseBundleExtra(tagName, attrs, outBundle) + } catch (e: Exception) { + pluginResources.parseBundleExtra(tagName, attrs, outBundle) + }*/ + try { - originResources.parseBundleExtra(tagName, attrs, outBundle) - } catch (e: Exception) { pluginResources.parseBundleExtra(tagName, attrs, outBundle) + } catch (e: Exception) { + originResources.parseBundleExtra(tagName, attrs, outBundle) } } @SuppressLint("NewApi") override fun addLoaders(vararg loaders: ResourcesLoader?) { - try { + /*try { originResources.addLoaders(*loaders) } catch (e: Exception) { pluginResources.addLoaders(*loaders) + }*/ + + try { + pluginResources.addLoaders(*loaders) + } catch (e: Exception) { + originResources.addLoaders(*loaders) } } @SuppressLint("NewApi") override fun removeLoaders(vararg loaders: ResourcesLoader?) { - try { + /*try { originResources.removeLoaders(*loaders) } catch (e: Exception) { pluginResources.removeLoaders(*loaders) + }*/ + + try { + pluginResources.removeLoaders(*loaders) + } catch (e: Exception) { + originResources.removeLoaders(*loaders) } } } diff --git a/core/src/main/java/io/github/fplus/plugin/activity/XplerActivity.kt b/core/src/main/java/io/github/fplus/plugin/activity/XplerActivity.kt index 99753f3..124316a 100644 --- a/core/src/main/java/io/github/fplus/plugin/activity/XplerActivity.kt +++ b/core/src/main/java/io/github/fplus/plugin/activity/XplerActivity.kt @@ -7,6 +7,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalContext +import androidx.core.view.WindowCompat import com.freegang.ktutils.extension.asOrNull import io.github.fplus.plugin.PluginClassloader import io.github.fplus.plugin.PluginContextThemeWrapper @@ -17,7 +18,7 @@ abstract class XplerActivity : BaseActivity() { private val mClassLoader: PluginClassloader? = null - private var mResources: PluginResources? = null + private var mResources: Resources? = null private val content = mutableStateOf<(@Composable () -> Unit)?>(null) @@ -29,13 +30,21 @@ abstract class XplerActivity : BaseActivity() { return mResources ?: super.getResources() } - override fun getAssets(): AssetManager = mResources?.pluginAssets ?: mResources?.assets ?: super.getAssets() + override fun getAssets(): AssetManager { + val resources = mResources + if (resources is PluginResources?) { + return resources?.pluginAssets ?: mResources?.assets ?: super.getAssets() + } + return mResources?.assets ?: super.getAssets() + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // actionBar?.hide() + WindowCompat.setDecorFitsSystemWindows(window, false) window.statusBarColor = android.graphics.Color.TRANSPARENT + window.navigationBarColor = android.graphics.Color.TRANSPARENT // val wrapper = PluginContextThemeWrapper(this) diff --git a/core/src/main/java/io/github/xpler/core/KtOnHook.kt b/core/src/main/java/io/github/xpler/core/KtOnHook.kt index f353bdf..02ce3b5 100644 --- a/core/src/main/java/io/github/xpler/core/KtOnHook.kt +++ b/core/src/main/java/io/github/xpler/core/KtOnHook.kt @@ -1,6 +1,7 @@ package io.github.xpler.core import com.freegang.ktutils.reflect.KReflectUtils +import com.freegang.ktutils.text.KTextUtils import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedHelpers @@ -118,7 +119,7 @@ annotation class OnConstructorReplace() * 并且还需在首位增加一个 [XC_MethodHook.MethodHookParam] 的方法参数 * 这是必要的 * - * @param name 应该是一个完整的类名, 如: com.sample.User + * @param name 应该是一个完整的类名, 如: com.sample.User;允许为 `”null“` 或 `”“` 字符串,将模糊匹配任意类型 */ @Target(AnnotationTarget.VALUE_PARAMETER) annotation class Param(val name: String) @@ -351,7 +352,8 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara methodHookImpl = MethodHookImpl(method) } } else { - methodHookImpl = MethodHookImpl(targetClazz, name, *paramTypes) + val normalParamTypes = paramTypes.map { it ?: Any::class.java }.toTypedArray() + methodHookImpl = MethodHookImpl(targetClazz, name, *normalParamTypes) } // 开启Hook @@ -456,7 +458,8 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara methodHookImpl = MethodHookImpl(method) } } else { - methodHookImpl = MethodHookImpl(targetClazz, name, *paramTypes) + val normalParamTypes = paramTypes.map { it ?: Any::class.java }.toTypedArray() + methodHookImpl = MethodHookImpl(targetClazz, name, *normalParamTypes) } // 开启Hook @@ -562,7 +565,8 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara methodHookImpl = MethodHookImpl(method) } } else { - methodHookImpl = MethodHookImpl(targetClazz, name, *paramTypes) + val normalParamTypes = paramTypes.map { it ?: Any::class.java }.toTypedArray() + methodHookImpl = MethodHookImpl(targetClazz, name, *normalParamTypes) } // 开启Hook @@ -589,7 +593,9 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara if (value.getAnnotation(OnConstructorReplace::class.java) != null) continue value.isAccessible = true - hookHelper?.constructor(*getTargetMethodParamTypes(value)) { + val paramTypes = getTargetMethodParamTypes(value) + val normalParamTypes = paramTypes.map { it ?: Any::class.java }.toTypedArray() + hookHelper?.constructor(*normalParamTypes) { onBefore { val invArgs = arrayOf(this, *argsOrEmpty) value.invoke(this@KtOnHook, *invArgs) @@ -611,7 +617,9 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara if (value.getAnnotation(OnConstructorReplace::class.java) != null) continue value.isAccessible = true - hookHelper?.constructor(*getTargetMethodParamTypes(value)) { + val paramTypes = getTargetMethodParamTypes(value) + val normalParamTypes = paramTypes.map { it ?: Any::class.java }.toTypedArray() + hookHelper?.constructor(*normalParamTypes) { onAfter { val invArgs = arrayOf(this, *argsOrEmpty) value.invoke(this@KtOnHook, *invArgs) @@ -631,7 +639,9 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara val methodMap = getAnnotationMethod(OnConstructorReplace::class.java) for ((_, value) in methodMap) { value.isAccessible = true - hookHelper?.constructor(*getTargetMethodParamTypes(value)) { + val paramTypes = getTargetMethodParamTypes(value) + val normalParamTypes = paramTypes.map { it ?: Any::class.java }.toTypedArray() + hookHelper?.constructor(*normalParamTypes) { onReplace { val invArgs = arrayOf(this, *argsOrEmpty) value.invoke(this@KtOnHook, *invArgs) @@ -672,7 +682,7 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara * @param method 目标方法 * @return Array */ - private fun getTargetMethodParamTypes(method: Method): Array> { + private fun getTargetMethodParamTypes(method: Method): Array?> { val parameterAnnotations = method.parameterAnnotations val parameterTypes = method.parameterTypes @@ -700,7 +710,7 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara private fun getTargetMethodParamTypesOnlyAnnotations( parameterAnnotations: Array>, parameterTypes: Array> - ): Array> { + ): Array?> { // 整理参数, 将第一个参数`XC_MethodHook.MethodHookParam`移除 val paramTypes = parameterTypes.toMutableList().apply { removeFirst() } @@ -709,7 +719,7 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara if (clazz == Any::class.java) { val param = parameterAnnotations[index++].filterIsInstance() .ifEmpty { return@map clazz } // 如果某个参数没有@Param注解, 直接return - findClass(param[0].name)// 寻找注解类 + findTargetParamClass(param[0].name)// 寻找注解类 } else { clazz } @@ -724,8 +734,8 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara */ private fun getTargetMethodParamTypesNormal( parameterAnnotations: Array>, - parameterTypes: Array> - ): Array> { + parameterTypes: Array?> + ): Array?> { // 整理参数、参数注解列表, 将第一个参数`XC_MethodHook.MethodHookParam`移除 val paramAnnotations = parameterAnnotations.toMutableList().apply { removeFirst() } val paramTypes = parameterTypes.toMutableList().apply { removeFirst() } @@ -735,12 +745,26 @@ abstract class KtOnHook(protected val lpparam: XC_LoadPackage.LoadPackagePara if (paramAnnotations[index].isEmpty()) return@mapIndexed clazz // 如果某个参数没有注解 val param = paramAnnotations[index].filterIsInstance() .ifEmpty { return@mapIndexed clazz } // 如果某个参数有注解, 但没有@Param注解, 直接return - findClass(param[0].name) // 寻找注解类 + findTargetParamClass(param[0].name) // 寻找注解类 }.toTypedArray() return finalParamTypes } + private fun findTargetParamClass( + name: String, + classLoader: ClassLoader? = null, + ): Class<*>? { + if (KTextUtils.isEmpty(name)) { + return null + } + return try { + XposedHelpers.findClass(name, classLoader ?: lpparam.classLoader) + } catch (e: Exception) { + return null + } + } + /** * 勾住所有普通方法 */