From 3339821411a4b5f392327c962f347b26fcfd6b53 Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Thu, 22 Sep 2022 16:34:15 +0800 Subject: [PATCH] Added new logger function in LoggerFactory, YukiHookAPI.Configs --- .../highcapable/yukihookapi/YukiHookAPI.md | 70 ++-- .../yukihookapi/hook/log/LoggerFactory.md | 260 +++++++++++++++ .../highcapable/yukihookapi/YukiHookAPI.kt | 46 ++- .../yukihookapi/hook/log/LoggerFactory.kt | 306 +++++++++++++++--- 4 files changed, 590 insertions(+), 92 deletions(-) diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md index d131bc06..3d52c3b5 100644 --- a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md +++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md @@ -242,21 +242,29 @@ object Configs > 对 API 相关功能的配置类。 -### debugTag - field +### debugLog - method ```kotlin:no-line-numbers -var debugTag: String +inline fun debugLog(initiate: YukiHookLogger.Configs.() -> Unit) ``` **变更记录** +`v1.1.0` `新增` + +**功能描述** + +> 配置 `YukiHookLogger.Configs` 相关参数。 + +

debugTag - field

+ +**变更记录** + `v1.0` `添加` -**功能描述** +`v1.1.0` `作废` -> 模块在调用 `logger` 时打印的日志 `TAG` 名称。 - -你可以方便地进行自定义,并可以在 `Logcat` 和 `XposedBridge.log` 中找到它们。 +请转移到 `YukiHookLogger.Configs.tag` ### isDebug - field @@ -274,25 +282,15 @@ var isDebug: Boolean 默认为开启状态,开启后模块将会向 `Logcat` 和 `XposedBridge.log` 打印详细的 Hook 日志,关闭后仅会打印 `E` 级别的日志。 -### isAllowPrintingLogs - field - -```kotlin:no-line-numbers -var isAllowPrintingLogs: Boolean -``` +

isAllowPrintingLogs - field

**变更记录** `v1.0.4` `新增` -**功能描述** +`v1.1.0` `作废` -> 是否启用调试日志的输出功能。 - -::: warning - -关闭后将会停用 **YukiHookAPI** 对全部日志的输出,但是不影响当你手动调用日志方法输出日志。 - -::: +请转移到 `YukiHookLogger.Configs.isEnable` ### isEnableModulePrefsCache - field @@ -446,7 +444,7 @@ inline fun configs(initiate: Configs.() -> Unit) **功能示例** -你可以在 `HookEntryClass` 的 `onInit` 方法中调用 `configs` 方法完成对 API 的功能配置,实时生效。 +你可以在 `HookEntryClass` 的 `onInit` 方法中调用 `configs` 方法和 `debugLog` 方法完成对 API 的功能配置,实时生效。 > 示例如下 @@ -455,12 +453,17 @@ class HookEntryClass : IYukiHookXposedInit { override fun onInit() { YukiHookAPI.configs { - debugTag = "YukiHookAPI" + debugLog { + tag = "YukiHookAPI" + isEnable = true + isRecord = false + elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID) + } isDebug = BuildConfig.DEBUG - isAllowPrintingLogs = true isEnableModulePrefsCache = true isEnableModuleAppResourcesCache = true isEnableHookModuleStatus = true + isEnableHookSharedPreferences = false isEnableDataChannel = true isEnableMemberCache = true } @@ -480,12 +483,17 @@ class HookEntryClass : IYukiHookXposedInit { class HookEntryClass : IYukiHookXposedInit { override fun onInit() = configs { - debugTag = "YukiHookAPI" + debugLog { + tag = "YukiHookAPI" + isEnable = true + isRecord = false + elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID) + } isDebug = BuildConfig.DEBUG - isAllowPrintingLogs = true isEnableModulePrefsCache = true isEnableModuleAppResourcesCache = true isEnableHookModuleStatus = true + isEnableHookSharedPreferences = false isEnableDataChannel = true isEnableMemberCache = true } @@ -496,7 +504,7 @@ class HookEntryClass : IYukiHookXposedInit { } ``` -你也可以不通过 `configs` 方法,直接进行配置。 +你也可以不通过 `configs` 和 `debugLog` 方法,直接进行配置。 > 示例如下 @@ -504,12 +512,20 @@ class HookEntryClass : IYukiHookXposedInit { class HookEntryClass : IYukiHookXposedInit { override fun onInit() { - YukiHookAPI.Configs.debugTag = "YukiHookAPI" + YukiHookLogger.Configs.tag = "YukiHookAPI" + YukiHookLogger.Configs.isEnable = true + YukiHookLogger.Configs.isRecord = false + YukiHookLogger.Configs.elements( + YukiHookLogger.Configs.TAG, + YukiHookLogger.Configs.PRIORITY, + YukiHookLogger.Configs.PACKAGE_NAME, + YukiHookLogger.Configs.USER_ID + ) YukiHookAPI.Configs.isDebug = BuildConfig.DEBUG - YukiHookAPI.Configs.isAllowPrintingLogs = true YukiHookAPI.Configs.isEnableModulePrefsCache = true YukiHookAPI.Configs.isEnableModuleAppResourcesCache = true YukiHookAPI.Configs.isEnableHookModuleStatus = true + YukiHookAPI.Configs.isEnableHookSharedPreferences = false YukiHookAPI.Configs.isEnableDataChannel = true YukiHookAPI.Configs.isEnableMemberCache = true } diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.md index 9dd0cd4e..b8e2e67c 100644 --- a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.md +++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.md @@ -98,6 +98,266 @@ BOTH 模块环境仅使用 `LOGD`。 +## YukiHookLogger - object + +```kotlin:no-line-numbers +object YukiHookLogger +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 调试日志实现类。 + +### contents - field + +```kotlin:no-line-numbers +val contents: String +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 获取当前日志文件内容。 + +如果当前没有已记录的日志会返回空字符串。 + +### clear - method + +```kotlin:no-line-numbers +fun clear() +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 清除全部已记录的日志。 + +### saveToFile - method + +```kotlin:no-line-numbers +fun saveToFile(fileName: String) +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 保存当前日志到文件。 + +若当前未开启 `Configs.isRecord` 或记录为空则不会进行任何操作。 + +日志文件会追加到 `fileName` 的文件结尾,若文件不存在会自动创建。 + +::: danger + +文件读写权限取决于当前宿主已获取的权限。 + +::: + +### Configs - object + +```kotlin:no-line-numbers +object Configs +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 配置 `YukiHookLogger`。 + +#### TAG - field + +```kotlin:no-line-numbers +const val TAG: Int +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 标签。 + +#### PRIORITY - field + +```kotlin:no-line-numbers +const val PRIORITY: Int +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 优先级。 + +#### PACKAGE_NAME - field + +```kotlin:no-line-numbers +const val PACKAGE_NAME: Int +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 当前宿主的包名。 + +#### USER_ID - field + +```kotlin:no-line-numbers +const val USER_ID: Int +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 当前宿主的用户 ID (主用户不显示)。 + +#### isEnable - field + +```kotlin:no-line-numbers +var isEnable: Boolean +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 是否启用调试日志的输出功能。 + +关闭后将会停用 `YukiHookAPI` 对全部日志的输出。 + +但是不影响当你手动调用下面这些方法输出日志。 + +`loggerD`、`loggerI`、`loggerW`、`loggerE`。 + +当 `isEnable` 关闭后 `YukiHookAPI.Configs.isDebug` 也将同时关闭。 + +#### isRecord - field + +```kotlin:no-line-numbers +var isRecord: Boolean +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 是否启用调试日志的记录功能。 + +开启后将会在内存中记录全部可用的日志和异常堆栈。 + +需要同时启用 [isEnable](#isenable-field) 才能有效。 + +::: danger + +过量的日志可能会导致宿主运行缓慢或造成频繁 GC。 + +::: + +开启后你可以调用 [YukiHookLogger.saveToFile](#savetofile-method) 实时保存日志到文件或使用 [YukiHookLogger.contents](#contents-field) 获取实时日志文件。 + +#### tag - field + +```kotlin:no-line-numbers +var tag: String +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 这是一个调试日志的全局标识。 + +默认文案为 `YukiHookAPI`。 + +你可以修改为你自己的文案。 + +#### elements - method + +```kotlin:no-line-numbers +fun elements(vararg item: Int) +``` + +**变更记录** + +`v1.1.0` `新增` + +**功能描述** + +> 自定义调试日志对外显示的元素。 + +只对日志记录和 `XposedBridge.log` 生效。 + +日志元素的排列将按照你在 `item` 中设置的顺序进行显示。 + +你还可以留空 `item` 以不显示除日志内容外的全部元素。 + +可用的元素有:`TAG`、`PRIORITY`、`PACKAGE_NAME`、`USER_ID`。 + +**功能示例** + +打印的日志样式将按照你设置的排列顺序和元素内容进行。 + +> 示例如下 + +```kotlin +elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID) +``` + +以上内容定义的日志将显示为如下样式。 + +> 示例如下 + +```:no-line-numbers +[YukiHookAPI][D][com.demo.test][999]--> This is a log +``` + +如果我们调整元素顺序以及减少个数,那么结果又会不一样。 + +> 示例如下 + +```kotlin +elements(PACKAGE_NAME, USER_ID, PRIORITY) +``` + +以上内容定义的日志将显示为如下样式。 + +> 示例如下 + +```:no-line-numbers +[com.demo.test][999][D]--> This is a log +``` + ## loggerD - method ```kotlin:no-line-numbers diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt index 05f6b14d..9180e2ca 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt @@ -42,7 +42,9 @@ import com.highcapable.yukihookapi.hook.core.finder.members.MethodFinder import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.factory.isTaiChiModuleActive import com.highcapable.yukihookapi.hook.factory.processName -import com.highcapable.yukihookapi.hook.log.* +import com.highcapable.yukihookapi.hook.log.YukiHookLogger +import com.highcapable.yukihookapi.hook.log.yLoggerE +import com.highcapable.yukihookapi.hook.log.yLoggerI import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.param.type.HookEntryType import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper @@ -164,14 +166,25 @@ object YukiHookAPI { */ object Configs { + /** + * 配置 [YukiHookLogger.Configs] 相关参数 + * @param initiate 方法体 + */ + inline fun debugLog(initiate: YukiHookLogger.Configs.() -> Unit) = YukiHookLogger.Configs.apply(initiate).build() + /** * 这是一个调试日志的全局标识 * - * 默认文案为 YukiHookAPI + * - ❗此方法已弃用 - 在之后的版本中将直接被删除 * - * 你可以修改为你自己的文案 + * - ❗请现在转移到 [debugLog] 并使用 [YukiHookLogger.Configs.tag] */ - var debugTag = "YukiHookAPI" + @Deprecated(message = "请使用新方式来实现此功能") + var debugTag + get() = YukiHookLogger.Configs.tag + set(value) { + YukiHookLogger.Configs.tag = value + } /** * 是否开启调试模式 - 默认启用 @@ -182,22 +195,23 @@ object YukiHookAPI { * * 请过滤 [debugTag] 即可找到每条日志 * - * 当 [isAllowPrintingLogs] 关闭后 [isDebug] 也将同时关闭 + * 当 [YukiHookLogger.Configs.isEnable] 关闭后 [isDebug] 也将同时关闭 */ var isDebug = true /** * 是否启用调试日志的输出功能 * - * - ❗关闭后将会停用 [YukiHookAPI] 对全部日志的输出 + * - ❗此方法已弃用 - 在之后的版本中将直接被删除 * - * 但是不影响当你手动调用下面这些方法输出日志 - * - * [loggerD]、[loggerI]、[loggerW]、[loggerE] - * - * 当 [isAllowPrintingLogs] 关闭后 [isDebug] 也将同时关闭 + * - ❗请现在转移到 [debugLog] 并使用 [YukiHookLogger.Configs.isEnable] */ - var isAllowPrintingLogs = true + @Deprecated(message = "请使用新方式来实现此功能") + var isAllowPrintingLogs + get() = YukiHookLogger.Configs.isEnable + set(value) { + YukiHookLogger.Configs.isEnable = value + } /** * 是否启用 [YukiHookModulePrefs] 的键值缓存功能 @@ -315,7 +329,7 @@ object YukiHookAPI { YukiHookBridge.packageParamCallback = { if (hooker.isNotEmpty()) hooker.forEach { it.assignInstance(packageParam = this) } - else yLoggerE(msg = "Failed to passing \"encase\" method because your hooker param is empty", isShowProcessName = false) + else yLoggerE(msg = "Failed to passing \"encase\" method because your hooker param is empty", isImplicit = true) } else printNoXposedEnvLog() } @@ -362,7 +376,7 @@ object YukiHookAPI { if (hooker.isNotEmpty()) { printSplashLog() hooker.forEach { it.assignInstance(packageParam = baseContext.packageParam) } - } else yLoggerE(msg = "Failed to passing \"encase\" method because your hooker param is empty", isShowProcessName = false)) + } else yLoggerE(msg = "Failed to passing \"encase\" method because your hooker param is empty", isImplicit = true)) else printNoXposedEnvLog() } @@ -372,12 +386,12 @@ object YukiHookAPI { isShowSplashLogOnceTime = false yLoggerI( msg = "Welcome to YukiHookAPI $API_VERSION_NAME($API_VERSION_CODE)! Using ${Status.executorName} API ${Status.executorVersion}", - isShowProcessName = false + isImplicit = true ) } /** 输出找不到 [XposedBridge] 的错误日志 */ - private fun printNoXposedEnvLog() = yLoggerE(msg = "Could not found XposedBridge in current space! Aborted", isShowProcessName = false) + private fun printNoXposedEnvLog() = yLoggerE(msg = "Could not found XposedBridge in current space! Aborted", isImplicit = true) /** * 通过 baseContext 创建 Hook 入口类 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/log/LoggerFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/log/LoggerFactory.kt index 20d6cf01..8b1d8419 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/log/LoggerFactory.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/log/LoggerFactory.kt @@ -25,15 +25,21 @@ * * This file is Created by fankes on 2022/2/3. */ -@file:Suppress("unused") +@file:Suppress("unused", "MemberVisibilityCanBePrivate") package com.highcapable.yukihookapi.hook.log +import android.system.ErrnoException import android.util.Log import com.highcapable.yukihookapi.YukiHookAPI +import com.highcapable.yukihookapi.hook.factory.current +import com.highcapable.yukihookapi.hook.utils.toStackTrace import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge import com.highcapable.yukihookapi.hook.xposed.parasitic.AppParasitics import de.robv.android.xposed.XposedBridge +import java.io.File +import java.text.SimpleDateFormat +import java.util.* /** * 需要打印的日志类型 @@ -71,31 +77,232 @@ enum class LoggerType { } /** - * 向控制台和 [XposedBridge] 打印日志 - 最终实现方法 - * @param format 日志打印的格式 - * @param type 日志打印的类型 - * @param tag 日志打印的标签 - * @param msg 日志打印的内容 - * @param e 异常堆栈信息 - * @param isShowProcessName 是否显示当前进程名称 - 仅限 [XposedBridge.log] + * 调试日志数据实现类 + * @param time 当前时间 + * @param tag 当前标签 + * @param priority 当前优先级 + * @param packageName 当前包名 + * @param userId 当前用户 ID + * @param msg 当前日志内容 + * @param throwable 当前异常堆栈 */ -private fun baseLogger(format: String, type: LoggerType, tag: String, msg: String, e: Throwable? = null, isShowProcessName: Boolean = true) { +internal class LoggerData internal constructor( + internal var time: String = "", + internal var tag: String = YukiHookLogger.Configs.tag, + internal var priority: String = "", + internal var packageName: String = "", + internal var userId: Int = 0, + internal var msg: String = "", + internal var throwable: Throwable? = null +) { + + /** 是否隐式打印 */ + internal var isImplicit = false + + init { + time = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.ROOT).format(Date()) + packageName = YukiHookBridge.hostProcessName.takeIf { it != "unknown" } ?: YukiHookBridge.modulePackageName + userId = AppParasitics.findUserId(packageName) + } + + /** + * 获取头部时间字符串 + * @return [String] + */ + internal val head get() = "$time ------ " + + override fun toString(): String { + var content = "" + YukiHookLogger.Configs.elements.takeIf { it.isNotEmpty() }?.forEach { + if (it == YukiHookLogger.Configs.TAG) content += "[$tag]" + if (it == YukiHookLogger.Configs.PRIORITY) content += "[$priority]" + if (it == YukiHookLogger.Configs.PACKAGE_NAME && isImplicit.not()) content += "[$packageName]" + if (it == YukiHookLogger.Configs.USER_ID && isImplicit.not() && userId != 0) content += "[$userId]" + } + return content.takeIf { it.isNotBlank() }?.let { "$content--> $msg" } ?: msg + } +} + +/** + * 调试日志实现类 + */ +object YukiHookLogger { + + /** 当前全部已记录的日志 */ + internal val inMemoryData = HashSet() + + /** + * 获取当前日志文件内容 + * + * 如果当前没有已记录的日志会返回空字符串 + * @return [String] + */ + val contents: String + get() { + var content = "" + inMemoryData.takeIf { it.isNotEmpty() }?.forEach { + content += "${it.head}$it\n" + it.throwable?.also { e -> + content += "${it.head}Dump stack trace for \"${e.current().name}\":\n" + content += e.toStackTrace() + } + } + return content + } + + /** 清除全部已记录的日志 */ + fun clear() = inMemoryData.clear() + + /** + * 保存当前日志到文件 + * + * 若当前未开启 [Configs.isRecord] 或记录为空则不会进行任何操作 + * + * 日志文件会追加到 [fileName] 的文件结尾 - 若文件不存在会自动创建 + * + * - ❗文件读写权限取决于当前宿主已获取的权限 + * @param fileName 完整文件名 - 例如 /data/data/.../files/xxx.log + * @throws ErrnoException 如果目标路径不可写 + */ + fun saveToFile(fileName: String) { + if (inMemoryData.isNotEmpty()) File(fileName).appendText(contents) + } + + /** + * 配置 [YukiHookLogger] + */ + object Configs { + + /** + * 标签 + * + * 显示效果如下 ↓ + * + * ``` + * [YukiHookAPI][...][...]--> ... + * ``` + */ + const val TAG = 1000 + + /** + * 优先级 + * + * 显示效果如下 ↓ + * + * ``` + * [...][E][...]--> ... + * ``` + */ + const val PRIORITY = 1001 + + /** + * 当前宿主的包名 + * + * 显示效果如下 ↓ + * + * ``` + * [...][com.demo.test][...]--> ... + * ``` + */ + const val PACKAGE_NAME = 1002 + + /** + * 当前宿主的用户 ID (主用户不显示) + * + * 显示效果如下 ↓ + * + * ``` + * [...][...][999]--> ... + * ``` + */ + const val USER_ID = 1003 + + /** 当前已添加的元素顺序列表数组 */ + internal var elements = arrayOf(TAG, PRIORITY, PACKAGE_NAME, USER_ID) + + /** + * 是否启用调试日志的输出功能 - 默认启用 + * + * - ❗关闭后将会停用 [YukiHookAPI] 对全部日志的输出 + * + * 但是不影响当你手动调用下面这些方法输出日志 + * + * [loggerD]、[loggerI]、[loggerW]、[loggerE] + * + * 当 [isEnable] 关闭后 [YukiHookAPI.Configs.isDebug] 也将同时关闭 + */ + var isEnable = true + + /** + * 是否启用调试日志的记录功能 - 默认不启用 + * + * 开启后将会在内存中记录全部可用的日志和异常堆栈 + * + * 需要同时启用 [isEnable] 才能有效 + * + * - ❗过量的日志可能会导致宿主运行缓慢或造成频繁 GC + * + * 开启后你可以调用 [YukiHookLogger.saveToFile] 实时保存日志到文件或使用 [YukiHookLogger.contents] 获取实时日志文件 + */ + var isRecord = false + + /** + * 这是一个调试日志的全局标识 + * + * 默认文案为 YukiHookAPI + * + * 你可以修改为你自己的文案 + */ + var tag = "YukiHookAPI" + + /** + * 自定义调试日志对外显示的元素 + * + * 只对日志记录和 [XposedBridge.log] 生效 + * + * 日志元素的排列将按照你在 [item] 中设置的顺序进行显示 + * + * 你还可以留空 [item] 以不显示除日志内容外的全部元素 + * + * 可用的元素有:[TAG]、[PRIORITY]、[PACKAGE_NAME]、[USER_ID] + * + * 默认排列方式如下 ↓ + * + * ``` + * [TAG][PRIORITY][PACKAGE_NAME][USER_ID]--> Message + * ``` + * @param item 自定义的元素数组 + */ + fun elements(vararg item: Int) { + elements = arrayOf(*item.toTypedArray()) + } + + /** 结束方法体 */ + @PublishedApi + internal fun build() = Unit + } +} + +/** + * 向控制台和 [XposedBridge] 打印日志 - 最终实现方法 + * @param type 日志打印的类型 + * @param data 日志数据 + * @param isImplicit 是否隐式打印 - 不会记录 - 也不会显示包名和用户 ID + */ +private fun baseLogger(type: LoggerType, data: LoggerData, isImplicit: Boolean = false) { /** 打印到 [Log] */ - fun loggerInLogd() = when (format) { - "D" -> Log.d(tag, msg) - "I" -> Log.i(tag, msg) - "W" -> Log.w(tag, msg) - "E" -> Log.e(tag, msg, e) - else -> Log.wtf(tag, msg, e) + fun loggerInLogd() = when (data.priority) { + "D" -> Log.d(data.tag, data.msg) + "I" -> Log.i(data.tag, data.msg) + "W" -> Log.w(data.tag, data.msg) + "E" -> Log.e(data.tag, data.msg, data.throwable) + else -> Log.wtf(data.tag, data.msg, data.throwable) } /** 打印到 [XposedBridge.log] */ - fun loggerInXposed() = runCatching { - YukiHookBridge.hostProcessName.also { - val appUserId = AppParasitics.findUserId(it) - XposedBridge.log("[$tag][$format]${if (isShowProcessName) (if (appUserId != 0) "[$it][$appUserId]" else "[$it]") else ""}--> $msg") - e?.also { e -> XposedBridge.log(e) } - } + fun loggerInXposed() { + XposedBridge.log(data.also { it.isImplicit = isImplicit }.toString()) + data.throwable?.also { e -> XposedBridge.log(e) } } when (type) { LoggerType.LOGD -> loggerInLogd() @@ -106,94 +313,95 @@ private fun baseLogger(format: String, type: LoggerType, tag: String, msg: Strin if (YukiHookBridge.hasXposedBridge) loggerInXposed() } } + if (isImplicit.not() && YukiHookLogger.Configs.isRecord) YukiHookLogger.inMemoryData.add(data) } /** * [YukiHookAPI] 向控制台和 [XposedBridge] 打印日志 - D * @param msg 日志打印的内容 - * @param isShowProcessName 是否显示当前进程名称 - 仅限 [XposedBridge.log] + * @param isImplicit 是否隐式打印 - 不会记录 - 也不会显示包名和用户 ID * @param isDisableLog 禁止打印日志 - 标识后将什么也不做 - 默认为 false */ -internal fun yLoggerD(msg: String, isShowProcessName: Boolean = true, isDisableLog: Boolean = false) { - if (YukiHookAPI.Configs.isAllowPrintingLogs.not() || isDisableLog) return - baseLogger(format = "D", LoggerType.BOTH, YukiHookAPI.Configs.debugTag, msg, isShowProcessName = isShowProcessName) +internal fun yLoggerD(msg: String, isImplicit: Boolean = false, isDisableLog: Boolean = false) { + if (YukiHookLogger.Configs.isEnable.not() || isDisableLog) return + baseLogger(LoggerType.BOTH, LoggerData(priority = "D", msg = msg), isImplicit) } /** * [YukiHookAPI] 向控制台和 [XposedBridge] 打印日志 - I * @param msg 日志打印的内容 - * @param isShowProcessName 是否显示当前进程名称 - 仅限 [XposedBridge.log] + * @param isImplicit 是否隐式打印 - 不会记录 - 也不会显示包名和用户 ID * @param isDisableLog 禁止打印日志 - 标识后将什么也不做 - 默认为 false */ -internal fun yLoggerI(msg: String, isShowProcessName: Boolean = true, isDisableLog: Boolean = false) { - if (YukiHookAPI.Configs.isAllowPrintingLogs.not() || isDisableLog) return - baseLogger(format = "I", LoggerType.BOTH, YukiHookAPI.Configs.debugTag, msg, isShowProcessName = isShowProcessName) +internal fun yLoggerI(msg: String, isImplicit: Boolean = false, isDisableLog: Boolean = false) { + if (YukiHookLogger.Configs.isEnable.not() || isDisableLog) return + baseLogger(LoggerType.BOTH, LoggerData(priority = "I", msg = msg), isImplicit) } /** * [YukiHookAPI] 向控制台和 [XposedBridge] 打印日志 - W * @param msg 日志打印的内容 - * @param isShowProcessName 是否显示当前进程名称 - 仅限 [XposedBridge.log] + * @param isImplicit 是否隐式打印 - 不会记录 - 也不会显示包名和用户 ID * @param isDisableLog 禁止打印日志 - 标识后将什么也不做 - 默认为 false */ -internal fun yLoggerW(msg: String, isShowProcessName: Boolean = true, isDisableLog: Boolean = false) { - if (YukiHookAPI.Configs.isAllowPrintingLogs.not() || isDisableLog) return - baseLogger(format = "W", LoggerType.BOTH, YukiHookAPI.Configs.debugTag, msg, isShowProcessName = isShowProcessName) +internal fun yLoggerW(msg: String, isImplicit: Boolean = false, isDisableLog: Boolean = false) { + if (YukiHookLogger.Configs.isEnable.not() || isDisableLog) return + baseLogger(LoggerType.BOTH, LoggerData(priority = "W", msg = msg), isImplicit) } /** * [YukiHookAPI] 向控制台和 [XposedBridge] 打印日志 - E * @param msg 日志打印的内容 * @param e 可填入异常堆栈信息 - 将自动完整打印到控制台 - * @param isShowProcessName 是否显示当前进程名称 - 仅限 [XposedBridge.log] + * @param isImplicit 是否隐式打印 - 不会记录 - 也不会显示包名和用户 ID * @param isDisableLog 禁止打印日志 - 标识后将什么也不做 - 默认为 false */ -internal fun yLoggerE(msg: String, e: Throwable? = null, isShowProcessName: Boolean = true, isDisableLog: Boolean = false) { - if (YukiHookAPI.Configs.isAllowPrintingLogs.not() || isDisableLog) return - baseLogger(format = "E", LoggerType.BOTH, YukiHookAPI.Configs.debugTag, msg, e, isShowProcessName) +internal fun yLoggerE(msg: String, e: Throwable? = null, isImplicit: Boolean = false, isDisableLog: Boolean = false) { + if (YukiHookLogger.Configs.isEnable.not() || isDisableLog) return + baseLogger(LoggerType.BOTH, LoggerData(priority = "E", msg = msg, throwable = e), isImplicit) } /** * 向控制台和 [XposedBridge] 打印日志 - D * * [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg] - * @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag] + * @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookLogger.Configs.tag] * @param msg 日志打印的内容 * @param type 日志打印的类型 - 默认为 [LoggerType.BOTH] */ -fun loggerD(tag: String = YukiHookAPI.Configs.debugTag, msg: String, type: LoggerType = LoggerType.BOTH) = - baseLogger(format = "D", type, tag, msg) +fun loggerD(tag: String = YukiHookLogger.Configs.tag, msg: String, type: LoggerType = LoggerType.BOTH) = + baseLogger(type, LoggerData(priority = "D", tag = tag, msg = msg)) /** * 向控制台和 [XposedBridge] 打印日志 - I * * [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg] - * @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag] + * @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookLogger.Configs.tag] * @param msg 日志打印的内容 * @param type 日志打印的类型 - 默认为 [LoggerType.BOTH] */ -fun loggerI(tag: String = YukiHookAPI.Configs.debugTag, msg: String, type: LoggerType = LoggerType.BOTH) = - baseLogger(format = "I", type, tag, msg) +fun loggerI(tag: String = YukiHookLogger.Configs.tag, msg: String, type: LoggerType = LoggerType.BOTH) = + baseLogger(type, LoggerData(priority = "I", tag = tag, msg = msg)) /** * 向控制台和 [XposedBridge] 打印日志 - W * * [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg] - * @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag] + * @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookLogger.Configs.tag] * @param msg 日志打印的内容 * @param type 日志打印的类型 - 默认为 [LoggerType.BOTH] */ -fun loggerW(tag: String = YukiHookAPI.Configs.debugTag, msg: String, type: LoggerType = LoggerType.BOTH) = - baseLogger(format = "W", type, tag, msg) +fun loggerW(tag: String = YukiHookLogger.Configs.tag, msg: String, type: LoggerType = LoggerType.BOTH) = + baseLogger(type, LoggerData(priority = "W", tag = tag, msg = msg)) /** * 向控制台和 [XposedBridge] 打印日志 - E * * [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg] - * @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag] + * @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookLogger.Configs.tag] * @param msg 日志打印的内容 * @param e 可填入异常堆栈信息 - 将自动完整打印到控制台 * @param type 日志打印的类型 - 默认为 [LoggerType.BOTH] */ -fun loggerE(tag: String = YukiHookAPI.Configs.debugTag, msg: String, e: Throwable? = null, type: LoggerType = LoggerType.BOTH) = - baseLogger(format = "E", type, tag, msg, e) \ No newline at end of file +fun loggerE(tag: String = YukiHookLogger.Configs.tag, msg: String, e: Throwable? = null, type: LoggerType = LoggerType.BOTH) = + baseLogger(type, LoggerData(priority = "E", tag = tag, msg = msg, throwable = e)) \ No newline at end of file