mirror of
https://github.com/BetterAndroid/Hikage.git
synced 2025-09-05 10:15:37 +08:00
refactor: migration to KavaRef
This commit is contained in:
@@ -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: <this>::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: <this>::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: <this>::lint
|
||||
lint-checks:
|
||||
|
@@ -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)
|
||||
|
@@ -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<AutoCloseable>("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 <T : Any> getDeclaredConstructors(declaringClass: Class<T>): List<Constructor<T>> =
|
||||
SystemVersion.require(SystemVersion.P, super.getDeclaredConstructors(declaringClass)) {
|
||||
HiddenApiBypass.getDeclaredMethods(declaringClass).filterIsInstance<Constructor<T>>().toList()
|
||||
}
|
||||
|
||||
override fun <T : Any> getDeclaredMethods(declaringClass: Class<T>): List<Method> =
|
||||
SystemVersion.require(SystemVersion.P, super.getDeclaredMethods(declaringClass)) {
|
||||
HiddenApiBypass.getDeclaredMethods(declaringClass).filterIsInstance<Method>().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<AssetsProvider>()
|
||||
).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<HikageAttrsView>(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<XmlResourceParser>(resId)
|
||||
?: error("Failed to create parser.")
|
||||
} else createViewAttrs()
|
||||
}
|
||||
}
|
@@ -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<HikageFactory>) {
|
||||
private const val LayoutParamsUnspecified = LayoutParamsWrapContent - 1
|
||||
|
||||
/** The view constructors map. */
|
||||
private val viewConstructors = mutableMapOf<String, ViewConstructor>()
|
||||
private val viewConstructors = mutableMapOf<String, ViewConstructor<*>>()
|
||||
|
||||
/** The view atomic id. */
|
||||
private val viewAtomicId = AtomicInteger(0x7F00000)
|
||||
@@ -143,7 +138,7 @@ class Hikage private constructor(private val factories: List<HikageFactory>) {
|
||||
attachToParent: Boolean = parent != null,
|
||||
factory: HikageFactoryBuilder.() -> Unit = {},
|
||||
performer: HikagePerformer<ViewGroup.LayoutParams>
|
||||
) = create(ViewGroup_LayoutParamsClass, context, parent, attachToParent, factory, performer)
|
||||
) = create(classOf<ViewGroup.LayoutParams>(), context, parent, attachToParent, factory, performer)
|
||||
|
||||
/**
|
||||
* Create a new [Hikage].
|
||||
@@ -195,7 +190,7 @@ class Hikage private constructor(private val factories: List<HikageFactory>) {
|
||||
fun build(
|
||||
factory: HikageFactoryBuilder.() -> Unit = {},
|
||||
performer: HikagePerformer<ViewGroup.LayoutParams>
|
||||
) = build(ViewGroup_LayoutParamsClass, factory, performer)
|
||||
) = build(classOf<ViewGroup.LayoutParams>(), factory, performer)
|
||||
|
||||
/**
|
||||
* Create a new [Hikage.Delegate].
|
||||
@@ -229,11 +224,11 @@ class Hikage private constructor(private val factories: List<HikageFactory>) {
|
||||
|
||||
/**
|
||||
* 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<V : View>(
|
||||
private val resolver: ConstructorResolver<V>,
|
||||
private val parameterCount: Int
|
||||
) {
|
||||
|
||||
@@ -243,11 +238,11 @@ class Hikage private constructor(private val factories: List<HikageFactory>) {
|
||||
* @param attrs the attribute set.
|
||||
* @return [V] or null.
|
||||
*/
|
||||
fun <V : View> 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<HikageFactory>) {
|
||||
/**
|
||||
* Get the view constructor.
|
||||
* @param viewClass the view class.
|
||||
* @return [ViewConstructor] or null.
|
||||
* @return [ViewConstructor]<[V]> or null.
|
||||
*/
|
||||
private fun <V : View> getViewConstructor(viewClass: Class<V>) =
|
||||
viewConstructors[viewClass.name] ?: run {
|
||||
viewConstructors[viewClass.name] as? ViewConstructor<V>? ?: 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<HikageFactory>) {
|
||||
factories.forEach { factory ->
|
||||
val params = PerformerParams(id, attrs, viewClass as Class<View>)
|
||||
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<HikageFactory>) {
|
||||
*/
|
||||
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<ViewGroup.LayoutParams?>(it)
|
||||
parameters(ViewGroup.LayoutParams::class)
|
||||
superclass()
|
||||
}?.invokeQuietly<ViewGroup.LayoutParams>(it)
|
||||
} ?: lparams
|
||||
return wrapped
|
||||
// Build a default.
|
||||
?: lpClass.buildOf<ViewGroup.LayoutParams>(LayoutParamsWrapContent, LayoutParamsWrapContent) {
|
||||
param(IntType, IntType)
|
||||
} ?: throw PerformerException("Create default layout params failed.")
|
||||
?: lpClass.createInstanceOrNull(LayoutParamsWrapContent, LayoutParamsWrapContent)
|
||||
?: throw PerformerException("Create default layout params failed.")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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<Context?>()
|
||||
resolve().optional(silent = true).firstFieldOrNull { name = "mContext" }?.getQuietly<Context>()
|
||||
?: error("Hikage need a Context to create PopupWindow content view.")
|
Reference in New Issue
Block a user