Added new functions to confirm the feature

This commit is contained in:
2022-03-18 04:10:34 +08:00
parent 106591e4f9
commit 8ee4d079d6
5 changed files with 128 additions and 26 deletions

View File

@@ -38,7 +38,7 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
@InjectYukiHookWithXposed
class HookEntry : YukiHookXposedInitProxy {
override fun onHook() {
override fun onInit() {
// 配置 YuKiHookAPI
// 可简写为 configs {}
YukiHookAPI.configs {
@@ -48,7 +48,14 @@ class HookEntry : YukiHookXposedInitProxy {
isDebug = true
// 是否启用调试日志的输出功能
isAllowPrintingLogs = true
// 是否启用 [YukiHookModulePrefs] 的键值缓存功能
// 若无和模块频繁交互数据在宿主重新启动之前建议开启
// 若需要实时交互数据建议关闭或从 [YukiHookModulePrefs] 中进行动态配置
isEnableModulePrefsCache = true
}
}
override fun onHook() {
// 开始你的 Hook
// 可简写为 encase {}
YukiHookAPI.encase {

View File

@@ -246,7 +246,13 @@ class YukiHookXposedProcessor : SymbolProcessorProvider {
" override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" +
" if (lpparam == null) return\n" +
" try {\n" +
" $className().onInit()\n" +
" if (YukiHookAPI.isXposedCallbackSetUp) {\n" +
" loggerE(tag = \"YukiHookAPI\", msg = \"You cannot loading a hooker in \\\"onInit\\\" method! Aborted\")\n" +
" return\n" +
" }\n" +
" $className().onHook()\n" +
" YukiHookAPI.onXposedInitialized()\n" +
" } catch (e: Throwable) {\n" +
" loggerE(tag = \"YukiHookAPI\", msg = \"YukiHookAPI try to load HookEntryClass failed\", e = e)\n" +
" }\n" +

View File

@@ -40,6 +40,7 @@ import com.highcapable.yukihookapi.hook.factory.processName
import com.highcapable.yukihookapi.hook.log.*
import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper
import com.highcapable.yukihookapi.hook.xposed.prefs.YukiHookModulePrefs
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.callbacks.XC_LoadPackage
@@ -60,12 +61,25 @@ object YukiHookAPI {
/** 是否还未输出欢迎信息 */
private var isShowSplashLogOnceTime = true
/** Xposed 是否装载完成 */
private var isXposedInitialized = false
/** 获取当前 [YukiHookAPI] 的版本 */
const val API_VERSION_NAME = "1.0.4"
/** 获取当前 [YukiHookAPI] 的版本号 */
const val API_VERSION_CODE = 5
/**
* 模块是否装载了 Xposed 回调方法
*
* - ❗此变量为私有功能性 API - 你不应该手动调用此变量
* @return [Boolean]
*/
@DoNotUseField
val isXposedCallbackSetUp
get() = !isXposedInitialized && packageParamCallback != null
/**
* 预设的 Xposed 模块包名
*
@@ -140,6 +154,15 @@ object YukiHookAPI {
* 当 [isAllowPrintingLogs] 关闭后 [isDebug] 也将同时关闭
*/
var isAllowPrintingLogs = true
/**
* 是否启用 [YukiHookModulePrefs] 的键值缓存功能
*
* - 为防止内存复用过高问题 - 此功能默认启用
*
* 你可以手动在 [YukiHookModulePrefs] 中自由开启和关闭缓存功能以及清除缓存
*/
var isEnableModulePrefsCache = true
}
/**
@@ -151,6 +174,16 @@ object YukiHookAPI {
*/
fun configs(initiate: Configs.() -> Unit) = Configs.apply(initiate)
/**
* 标识 Xposed API 装载完成
*
* - ❗装载代码将自动生成 - 你不应该手动使用此方法装载 Xposed 模块事件
*/
@DoNotUseMethod
fun onXposedInitialized() {
isXposedInitialized = true
}
/**
* 装载 Xposed API 回调
*

View File

@@ -79,6 +79,9 @@ class YukiHookModulePrefs(private val context: Context? = null) {
/** 缓存数据 */
private var xPrefCacheKeyValueFloats = HashMap<String, Float>()
/** 是否使用键值缓存 */
private var isUsingKeyValueCache = YukiHookAPI.Configs.isEnableModulePrefsCache
/** 检查是否处于自定义 Hook API 状态 */
private fun checkApiInBaseContext() {
if (YukiHookAPI.isLoadedFromBaseContext) error("YukiHookModulePrefs not allowed in Custom Hook API")
@@ -124,10 +127,24 @@ class YukiHookModulePrefs(private val context: Context? = null) {
* @return [YukiHookModulePrefs]
*/
fun name(name: String): YukiHookModulePrefs {
isUsingKeyValueCache = YukiHookAPI.Configs.isEnableModulePrefsCache
prefsName = name
return this
}
/**
* 忽略缓存直接读取键值
*
* 无论是否开启 [YukiHookAPI.Configs.isEnableModulePrefsCache]
*
* - 仅在 [XSharedPreferences] 下生效
* @return [YukiHookModulePrefs]
*/
fun direct(): YukiHookModulePrefs {
isUsingKeyValueCache = false
return this
}
/**
* 获取 [String] 键值
*
@@ -138,12 +155,14 @@ class YukiHookModulePrefs(private val context: Context? = null) {
*/
fun getString(key: String, default: String = "") =
(if (isXposedEnvironment)
xPrefCacheKeyValueStrings[key].let {
(it ?: xPref.getString(key, default) ?: default).let { value ->
xPrefCacheKeyValueStrings[key] = value
value
if (isUsingKeyValueCache)
xPrefCacheKeyValueStrings[key].let {
(it ?: xPref.getString(key, default) ?: default).let { value ->
xPrefCacheKeyValueStrings[key] = value
value
}
}
}
else xPref.getString(key, default) ?: default
else sPref.getString(key, default) ?: default).let {
makeWorldReadable()
it
@@ -159,12 +178,14 @@ class YukiHookModulePrefs(private val context: Context? = null) {
*/
fun getBoolean(key: String, default: Boolean = false) =
(if (isXposedEnvironment)
xPrefCacheKeyValueBooleans[key].let {
it ?: xPref.getBoolean(key, default).let { value ->
xPrefCacheKeyValueBooleans[key] = value
value
if (isUsingKeyValueCache)
xPrefCacheKeyValueBooleans[key].let {
it ?: xPref.getBoolean(key, default).let { value ->
xPrefCacheKeyValueBooleans[key] = value
value
}
}
}
else xPref.getBoolean(key, default)
else sPref.getBoolean(key, default)).let {
makeWorldReadable()
it
@@ -180,12 +201,14 @@ class YukiHookModulePrefs(private val context: Context? = null) {
*/
fun getInt(key: String, default: Int = 0) =
(if (isXposedEnvironment)
xPrefCacheKeyValueInts[key].let {
it ?: xPref.getInt(key, default).let { value ->
xPrefCacheKeyValueInts[key] = value
value
if (isUsingKeyValueCache)
xPrefCacheKeyValueInts[key].let {
it ?: xPref.getInt(key, default).let { value ->
xPrefCacheKeyValueInts[key] = value
value
}
}
}
else xPref.getInt(key, default)
else sPref.getInt(key, default)).let {
makeWorldReadable()
it
@@ -201,12 +224,14 @@ class YukiHookModulePrefs(private val context: Context? = null) {
*/
fun getFloat(key: String, default: Float = 0f) =
(if (isXposedEnvironment)
xPrefCacheKeyValueFloats[key].let {
it ?: xPref.getFloat(key, default).let { value ->
xPrefCacheKeyValueFloats[key] = value
value
if (isUsingKeyValueCache)
xPrefCacheKeyValueFloats[key].let {
it ?: xPref.getFloat(key, default).let { value ->
xPrefCacheKeyValueFloats[key] = value
value
}
}
}
else xPref.getFloat(key, default)
else sPref.getFloat(key, default)).let {
makeWorldReadable()
it
@@ -222,12 +247,14 @@ class YukiHookModulePrefs(private val context: Context? = null) {
*/
fun getLong(key: String, default: Long = 0L) =
(if (isXposedEnvironment)
xPrefCacheKeyValueLongs[key].let {
it ?: xPref.getLong(key, default).let { value ->
xPrefCacheKeyValueLongs[key] = value
value
if (isUsingKeyValueCache)
xPrefCacheKeyValueLongs[key].let {
it ?: xPref.getLong(key, default).let { value ->
xPrefCacheKeyValueLongs[key] = value
value
}
}
}
else xPref.getLong(key, default)
else sPref.getLong(key, default)).let {
makeWorldReadable()
it
@@ -321,4 +348,19 @@ class YukiHookModulePrefs(private val context: Context? = null) {
sPref.edit().putLong(key, value).apply()
makeWorldReadable()
}
/**
* 无论是否开启 [YukiHookAPI.Configs.isEnableModulePrefsCache]
*
* 调用此方法将清除当前存储的全部键值缓存
*
* 下次将从 [XSharedPreferences] 重新读取
*/
fun clearCache() {
xPrefCacheKeyValueStrings.clear()
xPrefCacheKeyValueBooleans.clear()
xPrefCacheKeyValueInts.clear()
xPrefCacheKeyValueLongs.clear()
xPrefCacheKeyValueFloats.clear()
}
}

View File

@@ -31,6 +31,7 @@ package com.highcapable.yukihookapi.hook.xposed.proxy
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
import com.highcapable.yukihookapi.hook.factory.configs
import com.highcapable.yukihookapi.hook.factory.encase
/**
@@ -38,14 +39,27 @@ import com.highcapable.yukihookapi.hook.factory.encase
*
* - ❗请在此类上添加注释 [InjectYukiHookWithXposed] 标记模块 Hook 入口
*
* [YukiHookAPI] 初始化时将自动调用 [onInit] 方法
*
* Hook 开始时将自动调用 [onHook] 方法
*
* 请在 [onInit] 中调用 [YukiHookAPI.configs] 或直接调用 [configs]
*
* 请在 [onHook] 中调用 [YukiHookAPI.encase] 或直接调用 [encase]
*
* 详情请参考 [YukiHookXposedInitProxy 接口](https://github.com/fankes/YukiHookAPI/wiki/%E4%BD%9C%E4%B8%BA-Xposed-%E6%A8%A1%E5%9D%97%E4%BD%BF%E7%94%A8%E7%9A%84%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE#yukihookxposedinitproxy-%E6%8E%A5%E5%8F%A3)
*/
interface YukiHookXposedInitProxy {
/**
* 配置 [YukiHookAPI.Configs] 的初始化方法
*
* - ❗在这里只能进行初始化配置 - 不能进行 Hook 操作
*
* 此方法可选 - 你也可以选择不对 [YukiHookAPI.Configs] 进行配置
*/
fun onInit() {}
/**
* 模块装载调用入口方法
*