diff --git a/gradle/sweet-dependency/sweet-dependency-config.yaml b/gradle/sweet-dependency/sweet-dependency-config.yaml index 75b4c8f..fb9adef 100644 --- a/gradle/sweet-dependency/sweet-dependency-config.yaml +++ b/gradle/sweet-dependency/sweet-dependency-config.yaml @@ -24,7 +24,7 @@ plugins: auto-update: false com.android.application: alias: android-application - version: 8.9.0 + version: 8.9.3 com.android.library: alias: android-library version-ref: android-application @@ -37,7 +37,7 @@ plugins: auto-update: false com.vanniktech.maven.publish: alias: maven-publish - version: 0.31.0 + version: 0.33.0 libraries: org.jetbrains.kotlin: @@ -54,7 +54,7 @@ libraries: version: 1.2.0 com.squareup: kotlinpoet: - version: 2.1.0 + version: 2.2.0 kotlinpoet-ksp: version-ref: ::kotlinpoet com.highcapable.betterandroid: @@ -67,20 +67,22 @@ libraries: org.lsposed.hiddenapibypass: hiddenapibypass: version: 6.1 - com.highcapable.yukireflection: - api: - version: 1.0.3 + com.highcapable.kavaref: + kavaref-core: + version: 1.0.0 + kavaref-extension: + version: 1.0.0 com.highcapable.pangutext: pangutext-android: version: 1.0.2 androidx.core: core: - version: 1.15.0 + version: 1.16.0 core-ktx: version-ref: ::core androidx.appcompat: appcompat: - version: 1.7.0 + version: 1.7.1 com.google.android.material: material: auto-update: false @@ -115,7 +117,7 @@ libraries: version: 1.4.0 androidx.compose.ui: ui: - version: 1.7.8 + version: 1.8.3 junit: junit: version: 4.13.2 @@ -127,7 +129,7 @@ libraries: version: 3.6.1 com.android.tools.lint: lint: - version: 31.9.0 + version: 31.11.0 lint-api: version-ref: ::lint lint-checks: diff --git a/hikage-core/build.gradle.kts b/hikage-core/build.gradle.kts index 18fa54a..7386bed 100644 --- a/hikage-core/build.gradle.kts +++ b/hikage-core/build.gradle.kts @@ -43,7 +43,8 @@ dependencies { lintPublish(projects.hikageCoreLint) ksp(projects.hikageCompiler) implementation(org.lsposed.hiddenapibypass.hiddenapibypass) - implementation(com.highcapable.yukireflection.api) + implementation(com.highcapable.kavaref.kavaref.core) + implementation(com.highcapable.kavaref.kavaref.extension) api(com.highcapable.betterandroid.ui.extension) implementation(com.highcapable.betterandroid.system.extension) implementation(androidx.core.core.ktx) diff --git a/hikage-core/src/main/java/com/highcapable/hikage/bypass/XmlBlockBypass.kt b/hikage-core/src/main/java/com/highcapable/hikage/bypass/XmlBlockBypass.kt index 793fd27..a064cbd 100644 --- a/hikage-core/src/main/java/com/highcapable/hikage/bypass/XmlBlockBypass.kt +++ b/hikage-core/src/main/java/com/highcapable/hikage/bypass/XmlBlockBypass.kt @@ -25,6 +25,7 @@ package com.highcapable.hikage.bypass import android.content.Context import android.content.pm.ApplicationInfo +import android.content.res.AssetManager import android.content.res.XmlResourceParser import android.content.res.loader.AssetsProvider import android.content.res.loader.ResourcesProvider @@ -34,14 +35,13 @@ import com.highcapable.betterandroid.system.extension.tool.SystemVersion import com.highcapable.betterandroid.ui.extension.view.inflateOrNull import com.highcapable.betterandroid.ui.extension.view.layoutInflater import com.highcapable.hikage.core.R -import com.highcapable.yukireflection.factory.classOf -import com.highcapable.yukireflection.factory.lazyClass -import com.highcapable.yukireflection.type.android.AssetManagerClass -import com.highcapable.yukireflection.type.java.BooleanType -import com.highcapable.yukireflection.type.java.IntType -import com.highcapable.yukireflection.type.java.LongType -import com.highcapable.yukireflection.type.java.StringClass +import com.highcapable.kavaref.KavaRef.Companion.resolve +import com.highcapable.kavaref.condition.type.Modifiers +import com.highcapable.kavaref.extension.lazyClass +import com.highcapable.kavaref.resolver.processor.MemberProcessor import org.lsposed.hiddenapibypass.HiddenApiBypass +import java.lang.reflect.Constructor +import java.lang.reflect.Method import android.R as Android_R /** @@ -101,7 +101,7 @@ internal object XmlBlockBypass { private val ApkAssetsClass by lazyClass("android.content.res.ApkAssets") /** The xml block class. */ - private val XmlBlockClass by lazyClass("android.content.res.XmlBlock") + private val XmlBlockClass by lazyClass("android.content.res.XmlBlock") /** Global pointer references object. */ private var xmlBlock: Long? = null @@ -112,6 +112,30 @@ internal object XmlBlockBypass { /** Whether the initialization is done once. */ private var isInitOnce = false + /** The resolver for member processor. */ + private val resolver = object : MemberProcessor.Resolver() { + + override fun getDeclaredConstructors(declaringClass: Class): List> = + SystemVersion.require(SystemVersion.P, super.getDeclaredConstructors(declaringClass)) { + HiddenApiBypass.getDeclaredMethods(declaringClass).filterIsInstance>().toList() + } + + override fun getDeclaredMethods(declaringClass: Class): List = + SystemVersion.require(SystemVersion.P, super.getDeclaredMethods(declaringClass)) { + HiddenApiBypass.getDeclaredMethods(declaringClass).filterIsInstance().toList() + } + } + + private val newParser by lazy { + XmlBlockClass.resolve() + .processor(resolver) + .optional() + .firstMethodOrNull { + name = "newParser" + parameters(Int::class) + } + } + /** * Initialize. * @param context the context. @@ -134,32 +158,40 @@ internal object XmlBlockBypass { SystemVersion.isHighOrEqualsTo(SystemVersion.R) -> // private static native long nativeLoad(@FormatType int format, @NonNull String path, // @PropertyFlags int flags, @Nullable AssetsProvider asset) throws IOException; - HiddenApiBypass.getDeclaredMethod( - ApkAssetsClass, "nativeLoad", - IntType, StringClass, IntType, classOf() - ).apply { isAccessible = true }.invoke(null, FORMAT_APK, sourceDir, PROPERTY_SYSTEM, null) + ApkAssetsClass.resolve() + .processor(resolver) + .optional() + .firstMethodOrNull { + name = "nativeLoad" + parameters(Int::class, String::class, Int::class, AssetsProvider::class) + modifiers(Modifiers.NATIVE) + }?.invokeQuietly(FORMAT_APK, sourceDir, PROPERTY_SYSTEM, null) SystemVersion.isHighOrEqualsTo(SystemVersion.P) -> // private static native long nativeLoad( // @NonNull String path, boolean system, boolean forceSharedLib, boolean overlay) // throws IOException; - HiddenApiBypass.getDeclaredMethod( - ApkAssetsClass, "nativeLoad", - StringClass, BooleanType, BooleanType, BooleanType - ).apply { isAccessible = true }.invoke(null, sourceDir, false, false, false) + ApkAssetsClass.resolve() + .processor(resolver) + .optional() + .firstMethodOrNull { + name = "nativeLoad" + parameters(String::class, Boolean::class, Boolean::class, Boolean::class) + modifiers(Modifiers.NATIVE) + }?.invokeQuietly(sourceDir, false, false, false) else -> error("Unsupported Android version.") } as? Long? ?: error("Failed to create ApkAssets.") - blockParser = when { - SystemVersion.isHighOrEqualsTo(36) -> - // XmlBlock(@Nullable AssetManager assets, long xmlBlock, boolean usesFeatureFlags) - HiddenApiBypass.getDeclaredConstructor(XmlBlockClass, AssetManagerClass, LongType, BooleanType) - .apply { isAccessible = true } - .newInstance(null, xmlBlock, false) - else -> - // XmlBlock(@Nullable AssetManager assets, long xmlBlock) - HiddenApiBypass.getDeclaredConstructor(XmlBlockClass, AssetManagerClass, LongType) - .apply { isAccessible = true } - .newInstance(null, xmlBlock) - } as? AutoCloseable? ?: error("Failed to create XmlBlock\$Parser.") + blockParser = XmlBlockClass.resolve() + .processor(resolver) + .optional() + .firstConstructorOrNull { + if (SystemVersion.isHighOrEqualsTo(36)) + parameters(AssetManager::class, Long::class, Boolean::class) + else parameters(AssetManager::class, Long::class) + }?.let { + if (SystemVersion.isHighOrEqualsTo(36)) + it.createQuietly(null, xmlBlock, false) + else it.createQuietly(null, xmlBlock) + } ?: error("Failed to create XmlBlock\$Parser.") isInitOnce = true } @@ -175,13 +207,13 @@ internal object XmlBlockBypass { * @return [XmlResourceParser] */ fun createViewAttrs() = context.layoutInflater.inflateOrNull(R.layout.layout_hikage_attrs_view)?.attrs - as? XmlResourceParser? ?: error("Failed to create AttributeSet.") + as? XmlResourceParser? ?: error("Failed to create AttributeSet.") return if (SystemVersion.isHighOrEqualsTo(SystemVersion.P)) { if (!isInitOnce) return createViewAttrs() require(blockParser != null) { "Hikage initialization failed." } - HiddenApiBypass.getDeclaredMethod(XmlBlockClass, "newParser", IntType) - .apply { isAccessible = true } - .invoke(blockParser, resId) as? XmlResourceParser? ?: error("Failed to create parser.") + newParser?.copy()?.of(blockParser) + ?.invokeQuietly(resId) + ?: error("Failed to create parser.") } else createViewAttrs() } } \ No newline at end of file diff --git a/hikage-core/src/main/java/com/highcapable/hikage/core/Hikage.kt b/hikage-core/src/main/java/com/highcapable/hikage/core/Hikage.kt index 0ce9d4f..6fdf889 100644 --- a/hikage-core/src/main/java/com/highcapable/hikage/core/Hikage.kt +++ b/hikage-core/src/main/java/com/highcapable/hikage/core/Hikage.kt @@ -61,17 +61,12 @@ import com.highcapable.hikage.core.base.HikageView import com.highcapable.hikage.core.base.PerformerException import com.highcapable.hikage.core.base.ProvideException import com.highcapable.hikage.core.extension.ResourcesScope -import com.highcapable.yukireflection.factory.buildOf -import com.highcapable.yukireflection.factory.classOf -import com.highcapable.yukireflection.factory.constructor -import com.highcapable.yukireflection.factory.current -import com.highcapable.yukireflection.factory.notExtends -import com.highcapable.yukireflection.type.android.AttributeSetClass -import com.highcapable.yukireflection.type.android.ContextClass -import com.highcapable.yukireflection.type.android.ViewGroup_LayoutParamsClass -import com.highcapable.yukireflection.type.java.IntType +import com.highcapable.kavaref.KavaRef.Companion.resolve +import com.highcapable.kavaref.extension.classOf +import com.highcapable.kavaref.extension.createInstanceOrNull +import com.highcapable.kavaref.extension.isNotSubclassOf +import com.highcapable.kavaref.resolver.ConstructorResolver import java.io.Serializable -import java.lang.reflect.Constructor import java.util.concurrent.atomic.AtomicInteger /** @@ -91,7 +86,7 @@ class Hikage private constructor(private val factories: List) { private const val LayoutParamsUnspecified = LayoutParamsWrapContent - 1 /** The view constructors map. */ - private val viewConstructors = mutableMapOf() + private val viewConstructors = mutableMapOf>() /** The view atomic id. */ private val viewAtomicId = AtomicInteger(0x7F00000) @@ -143,7 +138,7 @@ class Hikage private constructor(private val factories: List) { attachToParent: Boolean = parent != null, factory: HikageFactoryBuilder.() -> Unit = {}, performer: HikagePerformer - ) = create(ViewGroup_LayoutParamsClass, context, parent, attachToParent, factory, performer) + ) = create(classOf(), context, parent, attachToParent, factory, performer) /** * Create a new [Hikage]. @@ -195,7 +190,7 @@ class Hikage private constructor(private val factories: List) { fun build( factory: HikageFactoryBuilder.() -> Unit = {}, performer: HikagePerformer - ) = build(ViewGroup_LayoutParamsClass, factory, performer) + ) = build(classOf(), factory, performer) /** * Create a new [Hikage.Delegate]. @@ -229,11 +224,11 @@ class Hikage private constructor(private val factories: List) { /** * The view constructor class. - * @param instance the constructor instance. + * @param resolver the constructor resolver. * @param parameterCount the parameter count. */ - private inner class ViewConstructor( - private val instance: Constructor<*>, + private inner class ViewConstructor( + private val resolver: ConstructorResolver, private val parameterCount: Int ) { @@ -243,11 +238,11 @@ class Hikage private constructor(private val factories: List) { * @param attrs the attribute set. * @return [V] or null. */ - fun build(context: Context, attrs: AttributeSet) = when (parameterCount) { - 2 -> instance.newInstance(context, attrs) - 1 -> instance.newInstance(context) + fun build(context: Context, attrs: AttributeSet) = when (parameterCount) { + 2 -> resolver.createQuietly(context, attrs) + 1 -> resolver.createQuietly(context) else -> null - } as? V? + } } /** The performer set. */ @@ -333,17 +328,17 @@ class Hikage private constructor(private val factories: List) { /** * Get the view constructor. * @param viewClass the view class. - * @return [ViewConstructor] or null. + * @return [ViewConstructor]<[V]> or null. */ private fun getViewConstructor(viewClass: Class) = - viewConstructors[viewClass.name] ?: run { + viewConstructors[viewClass.name] as? ViewConstructor? ?: run { var parameterCount = 0 - val twoParams = viewClass.constructor { - param(ContextClass, AttributeSetClass) - }.ignored().give() - val onceParam = viewClass.constructor { - param(ContextClass) - }.ignored().give() + val twoParams = viewClass.resolve() + .optional(silent = true) + .firstConstructorOrNull { parameters(Context::class, AttributeSet::class) } + val onceParam = viewClass.resolve() + .optional(silent = true) + .firstConstructorOrNull { parameters(Context::class) } val constructor = onceParam?.apply { parameterCount = 1 } ?: twoParams?.apply { parameterCount = 2 } val viewConstructor = constructor?.let { ViewConstructor(it, parameterCount) } @@ -365,7 +360,7 @@ class Hikage private constructor(private val factories: List) { factories.forEach { factory -> val params = PerformerParams(id, attrs, viewClass as Class) val view = factory(parent, processed, context, params) - if (view != null && view.javaClass notExtends viewClass) throw PerformerException( + if (view != null && view.javaClass isNotSubclassOf viewClass) throw PerformerException( "HikageFactory cannot cast the created view type \"${view.javaClass}\" to \"${viewClass.name}\", " + "please confirm that the view type you created is correct." ) @@ -897,17 +892,16 @@ class Hikage private constructor(private val factories: List) { */ private fun createDefaultLayoutParams(lparams: ViewGroup.LayoutParams? = null): ViewGroup.LayoutParams { val wrapped = lparams?.let { - parent?.current(ignored = true)?.method { + parent?.resolve()?.optional(silent = true)?.firstMethodOrNull { name = "generateLayoutParams" - param(ViewGroup_LayoutParamsClass) - superClass() - }?.invoke(it) + parameters(ViewGroup.LayoutParams::class) + superclass() + }?.invokeQuietly(it) } ?: lparams return wrapped // Build a default. - ?: lpClass.buildOf(LayoutParamsWrapContent, LayoutParamsWrapContent) { - param(IntType, IntType) - } ?: throw PerformerException("Create default layout params failed.") + ?: lpClass.createInstanceOrNull(LayoutParamsWrapContent, LayoutParamsWrapContent) + ?: throw PerformerException("Create default layout params failed.") } /** diff --git a/hikage-extension-betterandroid/build.gradle.kts b/hikage-extension-betterandroid/build.gradle.kts index 4023487..0a4353d 100644 --- a/hikage-extension-betterandroid/build.gradle.kts +++ b/hikage-extension-betterandroid/build.gradle.kts @@ -39,7 +39,8 @@ android { dependencies { implementation(projects.hikageCore) - implementation(com.highcapable.yukireflection.api) + implementation(com.highcapable.kavaref.kavaref.core) + implementation(com.highcapable.kavaref.kavaref.extension) implementation(com.highcapable.betterandroid.ui.component) implementation(com.highcapable.betterandroid.ui.extension) implementation(com.highcapable.betterandroid.system.extension) diff --git a/hikage-extension-compose/build.gradle.kts b/hikage-extension-compose/build.gradle.kts index 7d4f2a8..07b283e 100644 --- a/hikage-extension-compose/build.gradle.kts +++ b/hikage-extension-compose/build.gradle.kts @@ -40,7 +40,8 @@ android { dependencies { implementation(projects.hikageCore) - implementation(com.highcapable.yukireflection.api) + implementation(com.highcapable.kavaref.kavaref.core) + implementation(com.highcapable.kavaref.kavaref.extension) implementation(com.highcapable.betterandroid.ui.extension) implementation(com.highcapable.betterandroid.system.extension) implementation(androidx.core.core.ktx) diff --git a/hikage-extension/build.gradle.kts b/hikage-extension/build.gradle.kts index 7aa84c2..b8a10b0 100644 --- a/hikage-extension/build.gradle.kts +++ b/hikage-extension/build.gradle.kts @@ -39,7 +39,8 @@ android { dependencies { implementation(projects.hikageCore) - implementation(com.highcapable.yukireflection.api) + implementation(com.highcapable.kavaref.kavaref.core) + implementation(com.highcapable.kavaref.kavaref.extension) implementation(com.highcapable.betterandroid.ui.extension) implementation(com.highcapable.betterandroid.system.extension) implementation(androidx.core.core.ktx) diff --git a/hikage-extension/src/main/java/com/highcapable/hikage/extension/PopupWindow.kt b/hikage-extension/src/main/java/com/highcapable/hikage/extension/PopupWindow.kt index a20647d..baaa36b 100644 --- a/hikage-extension/src/main/java/com/highcapable/hikage/extension/PopupWindow.kt +++ b/hikage-extension/src/main/java/com/highcapable/hikage/extension/PopupWindow.kt @@ -31,7 +31,7 @@ import com.highcapable.hikage.core.Hikage import com.highcapable.hikage.core.base.HikageFactoryBuilder import com.highcapable.hikage.core.base.HikagePerformer import com.highcapable.hikage.core.base.Hikageable -import com.highcapable.yukireflection.factory.current +import com.highcapable.kavaref.KavaRef.Companion.resolve /** * @see PopupWindow.setContentView @@ -67,5 +67,5 @@ fun PopupWindow.setContentView( * @return [Context] */ private fun PopupWindow.requireContext() = - current(ignored = true).field { name = "mContext" }.cast() + resolve().optional(silent = true).firstFieldOrNull { name = "mContext" }?.getQuietly() ?: error("Hikage need a Context to create PopupWindow content view.") \ No newline at end of file