diff --git a/modulesCommon.gradle b/modulesCommon.gradle index e1b436a48..3aeb5ac7d 100644 --- a/modulesCommon.gradle +++ b/modulesCommon.gradle @@ -34,6 +34,10 @@ android { } } + testOptions { + unitTests.returnDefaultValues = true + } + compileOptions { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 diff --git a/sdk/build.gradle b/sdk/build.gradle index 79789515b..326c66632 100644 --- a/sdk/build.gradle +++ b/sdk/build.gradle @@ -36,7 +36,6 @@ android { testOptions { unitTests.includeAndroidResources = true - unitTests.returnDefaultValues = true } tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { kotlinOptions { diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/logger/Level.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/logger/Level.kt index c03e3f412..d4585c3c0 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/logger/Level.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/logger/Level.kt @@ -1,6 +1,6 @@ package cloud.mindbox.mobile_sdk.logger -public enum class Level(public var value: Int) { +public enum class Level(public val value: Int) { VERBOSE(0), DEBUG(1), @@ -9,3 +9,8 @@ public enum class Level(public var value: Int) { ERROR(4), NONE(5) } + +internal infix fun Level.isAtMost(other: Level): Boolean = value <= other.value + +@Suppress("unused") +internal infix fun Level.isAtLeast(other: Level): Boolean = value >= other.value diff --git a/sdk/src/main/java/cloud/mindbox/mobile_sdk/logger/MindboxLoggerImpl.kt b/sdk/src/main/java/cloud/mindbox/mobile_sdk/logger/MindboxLoggerImpl.kt index a51335187..bfc825ff7 100644 --- a/sdk/src/main/java/cloud/mindbox/mobile_sdk/logger/MindboxLoggerImpl.kt +++ b/sdk/src/main/java/cloud/mindbox/mobile_sdk/logger/MindboxLoggerImpl.kt @@ -50,12 +50,32 @@ internal object MindboxLoggerImpl : MindboxLogger { internal var level: Level = DEFAULT_LOG_LEVEL /** - * All the methods below should be used only after Mindbox.initComponents method was called + * Returns [Level.DEBUG] if `adb shell setprop log.tag.Mindbox DEBUG` (or VERBOSE) is active, + * [Level.NONE] otherwise. Any other setprop value is treated as "not set". + * + * When [Level.DEBUG] is returned it overrides the programmatic [level], enabling all log + * output regardless of what [level] is currently configured to. + * + * `Log.isLoggable(TAG, Log.DEBUG)` returns `true` for both VERBOSE and DEBUG setprop values + * because VERBOSE has a lower priority than DEBUG in Android's priority scale. + * The property is consulted when execution reaches the setprop override check, so changes + * take effect immediately without app restart for calls that evaluate this branch. + * + * By design, only DEBUG and VERBOSE are supported as override values. WARN and ERROR could + * technically be detected (they make `isLoggable(INFO)` return `false`, unlike the default), + * but using setprop to make logging *more restrictive* than the SDK default serves no practical + * debugging purpose. INFO is indistinguishable from "no setprop" and is also intentionally + * ignored. Use [Mindbox.setLogLevel] for fine-grained programmatic control. */ + private fun setPropLevel(): Level = + if (Log.isLoggable(TAG, Log.DEBUG)) Level.DEBUG else Level.NONE + /** + * All the methods below should be used only after Mindbox.initComponents method was called + */ override fun i(parent: Any, message: String) { val logMessage = buildMessage(parent, message) - if (level.value <= Level.INFO.value) { + if (level isAtMost Level.INFO || setPropLevel() isAtMost Level.INFO) { Log.i(TAG, logMessage) } saveLog(logMessage) @@ -63,7 +83,7 @@ internal object MindboxLoggerImpl : MindboxLogger { override fun d(parent: Any, message: String) { val logMessage = buildMessage(parent, message) - if (level.value <= Level.DEBUG.value) { + if (level isAtMost Level.DEBUG || setPropLevel() isAtMost Level.DEBUG) { Log.d(TAG, logMessage) } saveLog(logMessage) @@ -71,7 +91,7 @@ internal object MindboxLoggerImpl : MindboxLogger { override fun e(parent: Any, message: String) { val logMessage = buildMessage(parent, message) - if (level.value <= Level.ERROR.value) { + if (level isAtMost Level.ERROR || setPropLevel() isAtMost Level.ERROR) { Log.e(TAG, logMessage) } saveLog(logMessage) @@ -79,7 +99,7 @@ internal object MindboxLoggerImpl : MindboxLogger { override fun e(parent: Any, message: String, exception: Throwable) { val logMessage = buildMessage(parent, message) - if (level.value <= Level.ERROR.value) { + if (level isAtMost Level.ERROR || setPropLevel() isAtMost Level.ERROR) { Log.e(TAG, logMessage, exception) } saveLog(logMessage + exception.stackTraceToString()) @@ -87,7 +107,7 @@ internal object MindboxLoggerImpl : MindboxLogger { override fun w(parent: Any, message: String) { val logMessage = buildMessage(parent, message) - if (level.value <= Level.WARN.value) { + if (level isAtMost Level.WARN || setPropLevel() isAtMost Level.WARN) { Log.w(TAG, logMessage) } saveLog(logMessage) @@ -95,7 +115,7 @@ internal object MindboxLoggerImpl : MindboxLogger { override fun w(parent: Any, message: String, exception: Throwable) { val logMessage = buildMessage(parent, message) - if (level.value <= Level.WARN.value) { + if (level isAtMost Level.WARN || setPropLevel() isAtMost Level.WARN) { Log.w(TAG, logMessage, exception) } saveLog(logMessage + exception.stackTraceToString())