diff --git a/app/src/main/java/cc/ioctl/hook/msg/MultiForwardAvatarHook.kt b/app/src/main/java/cc/ioctl/hook/msg/MultiForwardAvatarHook.kt index 75bb7ddac3..6069549f68 100644 --- a/app/src/main/java/cc/ioctl/hook/msg/MultiForwardAvatarHook.kt +++ b/app/src/main/java/cc/ioctl/hook/msg/MultiForwardAvatarHook.kt @@ -34,6 +34,7 @@ import android.widget.LinearLayout import android.widget.RelativeLayout import androidx.appcompat.widget.AppCompatTextView import androidx.core.text.buildSpannedString +import cc.hicore.QApp.QAppUtils import cc.ioctl.hook.profile.OpenProfileCard import cc.ioctl.util.HostInfo import cc.ioctl.util.HostStyledViewBuilder @@ -41,7 +42,6 @@ import cc.ioctl.util.LayoutHelper import cc.ioctl.util.Reflex import cc.ioctl.util.hookBeforeIfEnabled import cc.ioctl.util.ui.FaultyDialog -import com.github.kyuubiran.ezxhelper.utils.findMethod import com.github.kyuubiran.ezxhelper.utils.hookBefore import com.tencent.qqnt.kernel.nativeinterface.MsgRecord import de.robv.android.xposed.XC_MethodHook.MethodHookParam @@ -51,6 +51,7 @@ import io.github.qauxv.base.annotation.FunctionHookEntry import io.github.qauxv.base.annotation.UiItemAgentEntry import io.github.qauxv.dsl.FunctionEntryRouter import io.github.qauxv.hook.CommonSwitchFunctionHook +import io.github.qauxv.step.Step import io.github.qauxv.ui.CommonContextWrapper import io.github.qauxv.ui.CustomDialog import io.github.qauxv.util.Initiator @@ -58,7 +59,11 @@ import io.github.qauxv.util.Log import io.github.qauxv.util.QQVersion import io.github.qauxv.util.UiThread import io.github.qauxv.util.dexkit.CAIOUtils +import io.github.qauxv.util.dexkit.DexDeobfsProvider.getCurrentBackend +import io.github.qauxv.util.dexkit.DexKit import io.github.qauxv.util.dexkit.DexKit.loadClassFromCache +import io.github.qauxv.util.dexkit.DexKitFinder +import io.github.qauxv.util.dexkit.Multiforward_Avatar_setListener_NT import io.github.qauxv.util.requireMinQQVersion import me.ketal.dispacher.BaseBubbleBuilderHook import me.ketal.dispacher.OnBubbleBuilder @@ -69,7 +74,7 @@ import java.lang.reflect.Modifier @FunctionHookEntry @UiItemAgentEntry -object MultiForwardAvatarHook : CommonSwitchFunctionHook(arrayOf(CAIOUtils)), OnBubbleBuilder { +object MultiForwardAvatarHook : CommonSwitchFunctionHook(arrayOf(CAIOUtils, Multiforward_Avatar_setListener_NT)), OnBubbleBuilder, DexKitFinder { override val name = "转发消息点头像查看详细信息" override val description = "仅限合并转发的消息" @@ -77,24 +82,62 @@ object MultiForwardAvatarHook : CommonSwitchFunctionHook(arrayOf(CAIOUtils)), On private var mChatItemHeadIconViewId = 0 + + override val isNeedFind = QAppUtils.isQQnt() && Multiforward_Avatar_setListener_NT.descCache == null + + override fun doFind(): Boolean { + getCurrentBackend().use { backend -> + val dexKit = backend.getDexKitBridge() + val m = dexKit.findMethodCaller { + callerMethodDeclareClass = "com.tencent.mobileqq.aio.msglist.holder.component.avatar.AIOAvatarContentComponent" + callerMethodReturnType = "V" + callerMethodParameterTypes = emptyArray() + methodName = "setOnClickListener" + } + if (m.size != 1) return false + Multiforward_Avatar_setListener_NT.descCache = m.keys.first().descriptor + return true + } + } + + private val mStep: Step = object : Step { + override fun step(): Boolean { + return doFind() + } + + override fun isDone(): Boolean { + return !isNeedFind + } + + override fun getPriority(): Int { + return 0 + } + + override fun getDescription(): String { + return "点击事件相关方法查找中" + } + } + + override fun makePreparationSteps(): Array { + return arrayOf(mStep) + } + + @SuppressLint("DiscouragedApi") @Throws(Exception::class) public override fun initOnce(): Boolean { if (requireMinQQVersion(QQVersion.QQ_8_9_63)) { val clz = Initiator.loadClass("com.tencent.mobileqq.aio.msglist.holder.component.avatar.AIOAvatarContentComponent") // 设置头像点击和长按事件的方法 - clz.findMethod { - name == if (requireMinQQVersion(QQVersion.QQ_8_9_68)) "Q0" - else "R0" //8.9.63 - }.hookBefore { param -> + DexKit.requireMethodFromCache(Multiforward_Avatar_setListener_NT).hookBefore { param -> var layout: RelativeLayout? - clz.declaredFields.first { it.name == "h" }.let { + clz.declaredFields.single { it.name == "h" }.let { it.isAccessible = true //Lazy layout = (it.get(param.thisObject))!!.invoke("getValue") as RelativeLayout } if (layout!!.context.javaClass.name == "com.tencent.mobileqq.activity.MultiForwardActivity") { layout!!.setOnClickListener { - clz.declaredFields.first { + clz.declaredFields.single { it.type.name == "com.tencent.mobileqq.aio.msg.AIOMsgItem" }.let { it.isAccessible = true @@ -114,6 +157,8 @@ object MultiForwardAvatarHook : CommonSwitchFunctionHook(arrayOf(CAIOUtils)), On } return true } + + BaseBubbleBuilderHook.initialize() val kBaseBubbleBuilder = Initiator.loadClass("com/tencent/mobileqq/activity/aio/BaseBubbleBuilder") val onClick = kBaseBubbleBuilder.getMethod("onClick", View::class.java) diff --git a/app/src/main/java/io/github/qauxv/util/dexkit/DexKitTarget.kt b/app/src/main/java/io/github/qauxv/util/dexkit/DexKitTarget.kt index 3c68bb4c24..0bde29ae4f 100644 --- a/app/src/main/java/io/github/qauxv/util/dexkit/DexKitTarget.kt +++ b/app/src/main/java/io/github/qauxv/util/dexkit/DexKitTarget.kt @@ -763,3 +763,9 @@ data object FileBrowserActivity_InnerClass_onItemClick : DexKitTarget.UsingStrin override val declaringClass = "" override val filter = DexKitFilter.strInClsName("FileBrowserActivity") } + +data object Multiforward_Avatar_setListener_NT : DexKitTarget.UsingDexkit() { + override val findMethod: Boolean = true + override val declaringClass = "com.tencent.mobileqq.aio.msglist.holder.component.avatar.AIOAvatarContentComponent" + override val filter = DexKitFilter.allowAll +}