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