diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt index 0ab0105e..f3d26d2c 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt @@ -35,10 +35,13 @@ import com.highcapable.yukihookapi.YukiHookAPI.configs import com.highcapable.yukihookapi.YukiHookAPI.encase import com.highcapable.yukihookapi.annotation.DoNotUseMethod import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker +import com.highcapable.yukihookapi.hook.factory.hasClass import com.highcapable.yukihookapi.hook.factory.processName +import com.highcapable.yukihookapi.hook.log.loggerE import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus +import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.callbacks.XC_LoadPackage /** @@ -121,7 +124,9 @@ object YukiHookAPI { * @param initiate Hook 方法体 */ fun encase(initiate: PackageParam.() -> Unit) { - packageParamCallback = initiate + if (hasXposedBridge) + packageParamCallback = initiate + else printNoXposedBridge() } /** @@ -130,11 +135,13 @@ object YukiHookAPI { * @throws IllegalStateException 如果 [hooker] 是空的 */ fun encase(vararg hooker: YukiBaseHooker) { - packageParamCallback = { - if (hooker.isNotEmpty()) - hooker.forEach { it.assignInstance(packageParam = this) } - else error("Hooker is empty") - } + if (hasXposedBridge) + packageParamCallback = { + if (hooker.isNotEmpty()) + hooker.forEach { it.assignInstance(packageParam = this) } + else error("Hooker is empty") + } + else printNoXposedBridge() } /** @@ -173,7 +180,9 @@ object YukiHookAPI { * @param initiate Hook 方法体 */ fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit) { - if (baseContext != null) initiate.invoke(baseContext.packagePararm) + if (hasXposedBridge) + (if (baseContext != null) initiate.invoke(baseContext.packagePararm)) + else printNoXposedBridge() } /** @@ -209,16 +218,27 @@ object YukiHookAPI { * @throws IllegalStateException 如果 [hooker] 是空的 */ fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker) { - if (baseContext != null) - if (hooker.isNotEmpty()) - hooker.forEach { it.assignInstance(packageParam = baseContext.packagePararm) } - else error("Hooker is empty") + if (hasXposedBridge) + (if (baseContext != null) + if (hooker.isNotEmpty()) + hooker.forEach { it.assignInstance(packageParam = baseContext.packagePararm) } + else error("Hooker is empty")) + else printNoXposedBridge() } + /** 输出找不到 [XposedBridge] 的错误日志 */ + private fun printNoXposedBridge() = loggerE(msg = "Could not found XposedBridge in current space! Aborted") + /** * 通过 baseContext 创建 Hook 入口类 * @return [PackageParam] */ private val Context.packagePararm get() = PackageParam(PackageParamWrapper(packageName, processName, classLoader, applicationInfo)) + + /** + * 是否存在 [XposedBridge] + * @return [Boolean] + */ + internal val hasXposedBridge get() = ("de.robv.android.xposed.XposedBridge").hasClass } \ No newline at end of file diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt index 4e3a0dea..95970c01 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt @@ -79,6 +79,7 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla */ @DoNotUseMethod fun hook() { + if (!YukiHookAPI.hasXposedBridge) return if (hookMembers.isEmpty()) error("Hook Members is empty,hook aborted") hookMembers.forEach { (_, member) -> member.hook() } } @@ -296,6 +297,7 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla */ @DoNotUseMethod fun hook() { + if (!YukiHookAPI.hasXposedBridge) return /** 定义替换 Hook 回调方法体 */ val replaceMent = object : XC_MethodReplacement() { override fun replaceHookedMethod(baseParam: MethodHookParam?): Any? { diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt index 2b7a5c24..23fcc560 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt @@ -40,6 +40,18 @@ import java.lang.reflect.Method */ val String.clazz: Class<*> get() = Class.forName(this) +/** + * 通过字符串查找类是否存在 + * @return [Boolean] 是否存在 + */ +val String.hasClass + get() = try { + clazz + true + } catch (_: Throwable) { + false + } + /** * 查找方法是否存在 * @param name 名称