Added ModuleApplication function and merge findClass function to Xposed API

This commit is contained in:
2022-04-15 04:30:34 +08:00
parent 099ac65e55
commit b64c9a4d69
15 changed files with 287 additions and 21 deletions

View File

@@ -40,7 +40,8 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
dependencies {
// Used 82 API Version
compileOnly 'de.robv.android.xposed:api:82'
compileOnly fileTree(include: ['android-stub.jar'], dir: 'libs')
compileOnly fileTree(include: ['android-stub.jar', 'module-injector.jar'], dir: 'libs')
implementation fileTree(include: ['free-reflection.jar'], dir: 'libs')
implementation 'androidx.annotation:annotation:1.3.0'
}

Binary file not shown.

Binary file not shown.

View File

@@ -29,6 +29,7 @@
package com.highcapable.yukihookapi.hook.factory
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.bean.CurrentClass
import com.highcapable.yukihookapi.hook.bean.HookClass
import com.highcapable.yukihookapi.hook.core.finder.ConstructorFinder
@@ -36,6 +37,7 @@ import com.highcapable.yukihookapi.hook.core.finder.FieldFinder
import com.highcapable.yukihookapi.hook.core.finder.MethodFinder
import com.highcapable.yukihookapi.hook.core.finder.type.ModifierRules
import com.highcapable.yukihookapi.hook.store.MemberCacheStore
import de.robv.android.xposed.XposedHelpers
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.lang.reflect.Member
@@ -71,8 +73,16 @@ val String.hasClass get() = hasClass(loader = null)
fun classOf(name: String, loader: ClassLoader? = null): Class<*> {
val hashCode = ("[$name][$loader]").hashCode()
return MemberCacheStore.findClass(hashCode) ?: run {
(if (loader == null) Class.forName(name)
else loader.loadClass(name)).also { MemberCacheStore.putClass(hashCode, it) }
when {
YukiHookAPI.hasXposedBridge ->
runCatching { XposedHelpers.findClassIfExists(name, loader) }.getOrNull()
?: when (loader) {
null -> Class.forName(name)
else -> loader.loadClass(name)
}
loader == null -> Class.forName(name)
else -> loader.loadClass(name)
}.also { MemberCacheStore.putClass(hashCode, it) }
}
}

View File

@@ -0,0 +1,82 @@
/*
* YukiHookAPI - An efficient Kotlin version of the Xposed Hook API.
* Copyright (C) 2019-2022 HighCapable
* https://github.com/fankes/YukiHookAPI
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* This file is Created by fankes on 2022/4/15.
*/
package com.highcapable.yukihookapi.hook.xposed.application
import android.app.Application
import android.content.Context
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
import com.highcapable.yukihookapi.hook.xposed.application.inject.ModuleApplication_Injector
import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
import me.weishu.reflection.Reflection
/**
* 这是对使用 [YukiHookAPI] Xposed 模块实现中的一个扩展功能
*
* 在你的 Xposed 模块的 [Application] 中继承此类
*
* 或在 AndroidManifest.xml 的 application 标签中指定此类
*
* 目前可实现功能如下
*
* - 全局共享模块中静态的 [appContext]
*
* - 在模块与宿主中装载 [YukiHookAPI.Configs] 以确保 [YukiHookAPI.Configs.debugTag] 不需要重复定义
*
* - 在模块中使用系统隐藏 API - 核心技术引用了开源项目 [FreeReflection](https://github.com/tiann/FreeReflection)
*
* 详情请参考 [ModuleApplication](https://fankes.github.io/YukiHookAPI/#/api/document?id=moduleapplication-class)
*/
open class ModuleApplication : Application() {
companion object {
/** 全局静态 [Application] 实例 */
private var currentContext: ModuleApplication? = null
/**
* 全局静态 [Application] 实例
* @throws IllegalStateException 如果 [Application] 没有正确装载完成
*/
val appContext get() = currentContext ?: error("App is dead, You cannot call to appContext")
}
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
Reflection.unseal(base)
}
override fun onCreate() {
super.onCreate()
currentContext = this
callApiInit()
}
/** 调用入口类的 [YukiHookXposedInitProxy.onInit] 方法 */
private fun callApiInit() = runCatching { ModuleApplication_Injector.callApiInit() }
}