diff --git a/README.md b/README.md index c1c9b9bd..a290db5f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Eclipse Marketplace](https://img.shields.io/badge/build-passing-brightgreen) ![Eclipse Marketplace](https://img.shields.io/badge/license-MIT-blue) -![Eclipse Marketplace](https://img.shields.io/badge/version-v1.0.55-green) +![Eclipse Marketplace](https://img.shields.io/badge/version-v1.0.6-green) [![Telegram](https://img.shields.io/static/v1?label=Telegram&message=交流讨论&color=0088cc)](https://t.me/XiaofangInternet)

@@ -154,7 +154,16 @@ class MainHook : YukiHookXposedInitProxy { 修正一处注释错误;
临时修复一个 BUG;
增加了 `type` 中的大量 `android` 类型以及少量 `java` 类型;
- 修复新版与旧版 Kotlin APIs 的兼容性问题。 + 修复新版与旧版 Kotlin APIs 的兼容性问题。

+- 1.0.6
+ 修复 `YukiHookModulePrefs` 在使用一次 `direct` 忽略缓存后每次都忽略的 BUG;
+ 增加新的 API,作废了 `isActive` 判断模块激活的传统用法;
+ 修复非 Xposed 环境使用 API 时打印调试日志的问题;
+ 修复查找 `Field` 时的日志输出问题和未拦截的异常问题;
+ 解耦合 `ReflectionUtils` 中的 Xposed API;
+ 增加 `YukiHookModuleStatus` 方法名称的混淆,以精简模块生成的体积;
+ 装载模块自身 Hook 时将不再打印欢迎信息;
+ 修复上一个版本仍然存在的某些 BUG。 # Cooperations diff --git a/yukihookapi-ksp-xposed/src/api/kotlin/com/highcapable/yukihookapi_ksp_xposed/YukiHookXposedProcessor.kt b/yukihookapi-ksp-xposed/src/api/kotlin/com/highcapable/yukihookapi_ksp_xposed/YukiHookXposedProcessor.kt index dfecb37c..6e1a6bca 100644 --- a/yukihookapi-ksp-xposed/src/api/kotlin/com/highcapable/yukihookapi_ksp_xposed/YukiHookXposedProcessor.kt +++ b/yukihookapi-ksp-xposed/src/api/kotlin/com/highcapable/yukihookapi_ksp_xposed/YukiHookXposedProcessor.kt @@ -296,6 +296,7 @@ class YukiHookXposedProcessor : SymbolProcessorProvider { " object : XC_MethodReplacement() {\n" + " override fun replaceHookedMethod(param: MethodHookParam?) = XposedBridge.getXposedVersion()\n" + " })\n" + + " YukiHookAPI.isModulePackageXposedEnv = true" + " }\n" + " YukiHookAPI.modulePackageName = \"$realPackageName\"\n" + " YukiHookAPI.onXposedLoaded(lpparam)\n" + diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt index c8501040..3f974fe1 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt @@ -65,10 +65,10 @@ object YukiHookAPI { private var isXposedInitialized = false /** 获取当前 [YukiHookAPI] 的版本 */ - const val API_VERSION_NAME = "1.0.55" + const val API_VERSION_NAME = "1.0.6" /** 获取当前 [YukiHookAPI] 的版本号 */ - const val API_VERSION_CODE = 9 + const val API_VERSION_CODE = 10 /** * 模块是否装载了 Xposed 回调方法 @@ -80,6 +80,14 @@ object YukiHookAPI { val isXposedCallbackSetUp get() = !isXposedInitialized && packageParamCallback != null + /** + * 当前 Hook 的对象是模块自身 + * + * - ❗这是私有 API - 请勿手动修改 - 会引发未知异常 + */ + @DoNotUseField + var isModulePackageXposedEnv = false + /** * 预设的 Xposed 模块包名 * @@ -291,7 +299,7 @@ object YukiHookAPI { /** 输出欢迎信息调试日志 */ private fun printSplashLog() { - if (!Configs.isDebug || !isShowSplashLogOnceTime) return + if (!Configs.isDebug || !isShowSplashLogOnceTime || isModulePackageXposedEnv) return isShowSplashLogOnceTime = false yLoggerI(msg = "Welcome to YukiHookAPI $API_VERSION_NAME($API_VERSION_CODE)! Using $executorName API $executorVersion") } diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt index 8a54ba94..81755de8 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt @@ -89,7 +89,7 @@ class FieldFinder( } catch (e: Throwable) { Thread { SystemClock.sleep(10) - if (isNotIgnoredNoSuchMemberFailure) yLoggerE(msg = "NoSuchField happend in [$classSet] [${hookTag}]", e = e) + onFailureMsg(msg = "NoSuchField happend in [$classSet] [${hookTag}]", throwable = e) }.start() Result(isNoSuch = true, e) } @@ -122,10 +122,17 @@ class FieldFinder( /** * 得到变量实例处理类 + * + * - ❗如果目标对象不是静态 - 你必须设置 [instance] * @param instance 变量所在的实例对象 - 如果是静态可不填 - 默认 null * @return [Instance] */ - fun get(instance: Any? = null) = Instance(instance, give()?.get(instance)) + fun get(instance: Any? = null) = try { + Instance(instance, give()?.get(instance)) + } catch (e: Throwable) { + onFailureMsg(msg = "Try to get field instance failed", throwable = e) + Instance(instance, self = null) + } /** * 得到变量实例 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionUtils.java b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionUtils.java index d12386e3..ff242019 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionUtils.java +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionUtils.java @@ -36,8 +36,8 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; - -import de.robv.android.xposed.XposedHelpers; +import java.util.LinkedList; +import java.util.List; @SuppressWarnings("ALL") @DoNotUseClass @@ -181,10 +181,30 @@ public class ReflectionUtils { Class clz = clazz; if (returnType == null) return findMethodExact(clazz, methodName, parameterTypes); do { - Method[] methods = XposedHelpers.findMethodsByExactParameters(clazz, returnType, parameterTypes); + Method[] methods = findMethodsByExactParameters(clazz, returnType, parameterTypes); for (Method method : methods) if (method.getName().equals(methodName)) return method; } while ((clz = clz.getSuperclass()) != null); } throw new IllegalArgumentException("Can't find this method --> name:[" + methodName + "] returnType:[" + returnType.getName() + "] paramType:[" + getParametersString(parameterTypes) + "] in Class [" + clazz.getName() + "] by YukiHookAPI#finder"); } + + private static Method[] findMethodsByExactParameters(Class clazz, Class returnType, Class... parameterTypes) { + List result = new LinkedList(); + for (Method method : clazz.getDeclaredMethods()) { + if (returnType != null && returnType != method.getReturnType()) continue; + Class[] methodParameterTypes = method.getParameterTypes(); + if (parameterTypes.length != methodParameterTypes.length) continue; + boolean match = true; + for (int i = 0; i < parameterTypes.length; i++) { + if (parameterTypes[i] != methodParameterTypes[i]) { + match = false; + break; + } + } + if (!match) continue; + method.setAccessible(true); + result.add(method); + } + return result.toArray(new Method[result.size()]); + } }