Skip to content

Commit

Permalink
Merge pull request #57
Browse files Browse the repository at this point in the history
[fix] 修复聊天列表卡顿
  • Loading branch information
Mingyueyixi authored Aug 3, 2024
2 parents 627be71 + 82b0619 commit 86809f4
Showing 1 changed file with 34 additions and 232 deletions.
266 changes: 34 additions & 232 deletions app/src/main/java/com/lu/wxmask/plugin/CommonPlugin.kt
Original file line number Diff line number Diff line change
@@ -1,271 +1,73 @@
package com.lu.wxmask.plugin

import android.content.Context
import android.database.Cursor
import com.lu.lposed.api2.XC_MethodHook2
import com.lu.lposed.api2.XposedHelpers2
import com.lu.lposed.plugin.IPlugin
import com.lu.lposed.plugin.PluginProviders
import com.lu.magic.util.CursorUtil
import com.lu.magic.util.log.LogUtil
import com.lu.wxmask.BuildConfig
import com.lu.wxmask.ClazzN
import de.robv.android.xposed.callbacks.XC_LoadPackage

class CommonPlugin : IPlugin {

override fun handleHook(context: Context, lpparam: XC_LoadPackage.LoadPackageParam) {
// if (!BuildConfig.DEBUG) {
// return
// }
// LogUtil.w("WeChat MainUI not found Adapter for ListView, guess start.")
// val setAdapterMethod = XposedHelpers2.findMethodExactIfExists(
// ListView::class.java.name,
// context.classLoader,
// "setAdapter",
// ListAdapter::class.java
// )
// if (setAdapterMethod == null) {
// LogUtil.w( "setAdapterMethod is null")
// return
// }
// XposedHelpers2.hookMethod(
// setAdapterMethod,
// object : XC_MethodHook2() {
// override fun afterHookedMethod(param: MethodHookParam) {
// val adapter = param.args[0] ?: return
// LogUtil.i("hook List adapter ", adapter)
// }
// }
// )
companion object {
// 查询消息记录
private const val SQL_SELECT_MESSAGE =
"SELECT type, subtype, entity_id, aux_index, MAX(timestamp) as maxTime, count(aux_index) as msgCount, talker FROM FTS5MetaMessage"

// HookPointManager.INSTANCE.init(context, lpparam)
// 单聊搜索关键词记录
private const val SQL_SELECT_MESSAGES_BY_KEYWORD =
"SELECT FTS5MetaMessage.docid, type, subtype, entity_id, aux_index, timestamp, talker FROM FTS5MetaMessage"
}

// XposedHelpers2.findAndHookMethod(
// ClazzN.from("com.tencent.mm.sdk.platformtools.p2"),
// "getLogLevel",
// java.lang.Long.TYPE,
// object : XC_MethodHook2() {
// override fun afterHookedMethod(param: MethodHookParam) {
// param.result = 0
// XposedHelpers2.setStaticIntField(ClazzN.from("com.tencent.mm.sdk.platformtools.k2"), "a", 0)
// }
// })
//
// XposedHelpers2.findMethodsByExactPredicate(ClazzN.from("com.tencent.mm.sdk.platformtools.p2")) { m ->
// return@findMethodsByExactPredicate m.name.startsWith("log")
// }.forEach {
// XposedHelpers2.hookMethod(it, object : XC_MethodHook2() {
// override fun afterHookedMethod(param: MethodHookParam) {
// LogUtil.d("wxLog: ", param.args)
// }
// })
// }
//
// XposedHelpers2.findMethodsByExactPredicate(ClazzN.from("com.tencent.mars.xlog.Xlog")) { m ->
// return@findMethodsByExactPredicate m.name.startsWith("log") || m.name == "getLogLevel"
// }.forEach {
// if (it.name == "getLogLevel") {
// XposedHelpers2.hookMethod(it, object : XC_MethodHook2() {
// override fun afterHookedMethod(param: MethodHookParam) {
// param.result = 0
// }
// })
// } else {
// XposedHelpers2.hookMethod(it, object : XC_MethodHook2() {
// override fun afterHookedMethod(param: MethodHookParam) {
// LogUtil.d("wxLogXLog: ", param.args)
// }
// })
// }
// }
// 缓存正则表达式
private val regex by lazy {
Regex("^SELECT (FTS5MetaContact|FTS5MetaTopHits|FTS5MetaKefuContact|FTS5MetaFeature|FTS5MetaWeApp|FTS5MetaFinderFollow|FTS5MetaFavorite)\\.docid, type, subtype, entity_id, aux_index,.*")
}

override fun handleHook(context: Context, lpparam: XC_LoadPackage.LoadPackageParam) {

XposedHelpers2.findMethodsByExactPredicate(ClazzN.from("com.tencent.wcdb.database.SQLiteDatabase")) { m ->
if (m.name == "rawQueryWithFactory") {
LogUtil.d("rawQueryWithFactory", m.parameterTypes.size)
return@findMethodsByExactPredicate m.parameterTypes.size == 4
}
false
}.onEach {
XposedHelpers2.hookMethod(it, object : XC_MethodHook2() {
}.onEach { method ->
XposedHelpers2.hookMethod(method, object : XC_MethodHook2() {
override fun beforeHookedMethod(param: MethodHookParam) {
// LogUtil.d("sql rawQueryWithFactory:", param.args[1], param.args[2], param.args[3])
// val sourceData = CursorUtil.getAll(cursor, true, true)
// LogUtil.d("sql rawQueryWithFactory result:", sourceData)
//通过拦截sql语句,来隐藏搜索,或者通过cursor代理来隐藏

var sql = param.args[1].toString()
val sql = param.args[1].toString()
val wxMaskPlugin = PluginProviders.from(WXMaskPlugin::class.java)
//sql 中,aux_index 列必须存在,因为接下来需要用来重新构造sql并过滤
val regexResult =
Regex("^SELECT (FTS5MetaContact|FTS5MetaTopHits|FTS5MetaKefuContact|FTS5MetaFeature|FTS5MetaWeApp|FTS5MetaFinderFollow|FTS5MetaFavorite)\\.docid, type, subtype, entity_id, aux_index,.*").find(
sql
)
val needReplace = wxMaskPlugin.maskIdList.isNotEmpty()
&& (regexResult != null
// 查消息记录的
//SELECT type, subtype, entity_id, aux_index, MAX(timestamp) as maxTime, count(aux_index) as msgCount, talker FROM FTS5MetaMessage NOT INDEXED JOIN FTS5IndexMessage ON (FTS5MetaMessage.docid = FTS5IndexMessage.rowid) WHERE FTS5IndexMessage MATCH '("我")' AND status >= 0 GROUP BY aux_index ORDER BY timestamp desc LIMIT 4;
|| sql.startsWith("SELECT type, subtype, entity_id, aux_index, MAX(timestamp) as maxTime, count(aux_index) as msgCount, talker FROM FTS5MetaMessage ")
//单聊搜索关键词查记录
|| sql.startsWith("SELECT FTS5MetaMessage.docid, type, subtype, entity_id, aux_index, timestamp, talker FROM FTS5MetaMessage")
)

// sql.startsWith("SELECT FTS5MetaTopHits.docid")
// || sql.startsWith("SELECT FTS5MetaContact.docid")
// || sql.startsWith("SELECT FTS5MetaKefuContact.docid")
// || sql.startsWith("SELECT FTS5MetaFeature.docid")
// || sql.startsWith("SELECT FTS5MetaWeApp.docid")
// || sql.startsWith("SELECT FTS5MetaFinderFollow.docid")
// || sql.startsWith("SELECT FTS5MetaFavorite.docid"))
if (wxMaskPlugin.maskIdList.isNotEmpty()) {
val needReplace =
regex.containsMatchIn(sql) ||
sql.startsWith(SQL_SELECT_MESSAGE) ||
sql.startsWith(SQL_SELECT_MESSAGES_BY_KEYWORD)

if (needReplace) {
val hideValueText = StringBuilder()
for ((index, s) in wxMaskPlugin.maskIdList.withIndex()) {
hideValueText.append("\"$s\"")
if (index < wxMaskPlugin.maskIdList.size - 1) {
hideValueText.append(",")
}
}
if (needReplace) {
val hideValueText =
wxMaskPlugin.maskIdList.joinToString(",") { "\"$it\"" }

if (sql.endsWith(";")) {
sql = sql.substring(0, sql.length - 1)
}
//对原始sql包围一层,过滤掉指定用户
val sql2 = "SELECT * FROM ($sql) AS a WHERE aux_index NOT IN ($hideValueText);"
val sql2 = if (sql.endsWith(";")) {
sql.dropLast(1)
} else {
sql
}.let { "SELECT * FROM ($it) AS a WHERE aux_index NOT IN ($hideValueText);" }

param.args[1] = sql2
LogUtil.d("sql hide hit:", sql2)
param.args[1] = sql2
LogUtil.d("sql hide hit:", sql2)
}
}
// val result = XposedHelpers2.invokeOriginalMethod(param.method, param.thisObject, param.args)

// if (result is Cursor) {
// LogUtil.d("sql:", sql, param.args[2])
// LogUtil.d("sql result:", CursorUtil.getAll(result, true, true))
// }
// return result
}

override fun afterHookedMethod(param: MethodHookParam) {
// 不打印,开发者自己打开来调试。
// for debug watch sql query result
// if (BuildConfig.DEBUG) {
// LogUtil.d("sql: ", param.args[1])
// LogUtil.d("sql reqult: ", CursorUtil.getAll(param.result as Cursor?, true, true))
// }
// Ignore
}
})

}

}

// private fun proxyCursor(cursor: Cursor, filterList: List<Map<String, Any?>>): Any {
// if (!Proxy.isProxyClass(cursor::class.java)) {
// // 创建代理类
// Proxy.newProxyInstance(
// cursor.javaClass.getClassLoader(),
// cursor.javaClass.getInterfaces(),
// CursorProxy(cursor, filterList)
// )
// }
// return cursor
//
// }

}

//class WxCursorWrap(val cursor: Cursor, val filterList: List<Map<String, Any?>>) : AbstractCursor {
// override fun getCount(): Int {
// return filterList.size
// }
//
// private inline fun getValue(column: Int): Any? {
// val columnName = getColumnName(column)
// return filterList[position][columnName]
// }
//
// override fun getColumnNames(): Array<String> {
// return cursor.columnNames
// }
//
// override fun getString(column: Int): String? {
// val result = getValue(column)
// return result?.toString()
// }
//
// override fun getShort(column: Int): Short? {
// val result = getValue(column)
// if (result is Short) {
// return result
// }
// return if (result is Number) {
// result.toShort()
// } else {
// result.toString().toShortOrNull()
// }
// }
//
// override fun getInt(column: Int): Int {
// val result = getValue(column)
// if (result is Int) {
// return result
// }
// return if (result is Number) {
// result.toInt()
// } else {
// result.toString().toIntOrNull() ?: 0
// }
// }
//
// override fun getLong(column: Int): Long {
// val result = getValue(column)
// if (result is Long) {
// return result
// }
// return if (result is Number) {
// result.toLong()
// } else {
// result.toString().toLongOrNull() ?: 0
// }
// }
//
// override fun getFloat(column: Int): Float {
// val result = getValue(column)
// return if (result is Float) {
// result
// } else if (result is Number) {
// result.toFloat()
// }else{
// result.toString().toFloatOrNull() ?: 0f
// }
// }
//
// override fun getDouble(column: Int): Double {
// val result = getValue(column)
// return if (result is Double) {
// result
// } else if (result is Number) {
// result.toDouble()
// }else {
// result.toString().toDoubleOrNull() ?: 0.0
// }
// }
//
// override fun isNull(column: Int): Boolean {
// return getValue(column) == null
// }
//
//}
//
//class CursorProxy(val cursor: Cursor, val filterList: List<Map<String, Any?>>) : InvocationHandler {
//
// override fun invoke(proxy: Any?, method: Method, args: Array<out Any>?): Any {
// if ("getCount" == method.name) {
// return filterList.size
// }
// if ()
// return method.invoke(cursor, args)
// }
//
//}
}

0 comments on commit 86809f4

Please sign in to comment.