Potato icon indicating copy to clipboard operation
Potato copied to clipboard

Android: Setprop To Log and Quick Test

Open yunshuipiao opened this issue 5 years ago • 0 comments

[TOC]

日志

每一个Android App 都会有自己的日志系统。

推荐将日志模块放在工具类模块中,不要出现一个项目中存在多个日志工具类的情况。

如果是 sdk ,将日志模块的可见性设为模块内可见。

一般都会对日志进行封装,加上自定义的tag。如下

object LogTest {

    val tag = "LogTest"

    fun d(msg: String) {
        this.d(tag, msg)
    }
    
    fun d(tag: String, msg: String) {
        if (tag.isBlank()) {
            // 或者第三方日志工具
            Log.d(this.tag, msg)
        } else {
            Log.d(tag, msg)
        }
    }
}

接着需要控制何时对日志进行输入,比如常见的在 Debug 下输出,Release 下不输出。

常见的有三种方式:

Debug 变量控制

可以使用一个变量来控制是否输出日志。如下:

private var debug = true

fun d(tag: String, msg: String) {
    if (debug) {
        val t = if (tag.isBlank()) this.tag else tag
        Log.d(t, msg)
    }
}

缺点:每次发布都需要修改变量值来控制,麻烦且容易出错,淘汰。

BuildConfig.DEBUG 控制

private var debug = BuildConfig.DEBUG

由 BuildConfig.DEBUG 来动态控制,不需手动修改。

缺点:上面提到,将日志工具类放在底层工具模块中,此时 BuildConfig.DEBUG 的值永远为 false,日志无法输出。只有在 app 模块中,BuildConfig.DEBUG 值才能根据 Debug 和 Release 版本控制。淘汰

ApplicationInfo 的 flag 控制

isDebug = (application.applicationInfo.flags
        and ApplicationInfo.FLAG_DEBUGGABLE) != 0

可以使用上述的 debug 值来控制。并且推荐将改值放在底层工具类中,支持整个项目使用。

setprop

在 adb shell 的命令中,有一对命令

adb shell setprop [key] [value]
adb shell getprop [key]

可以设置系统属性和读取系统属性。

其中 adb shell setprop log.tag.x DEBUG 这个命令设置系统属性。

Log.isLogger(tag, leval) 的返回值是 boolean 类型,来控制日志输出。

其中 log.tag.x 为key, x表示自定义的tag,DEBUG(V, D, I, E) 表示日志级别(默认为 INFO)。

只有当 Log.isLogger(tag, leval) 的 tag 相等, leval 大于等于 命令行设置的参数是,才进行日志输出。

所以日志输出的最终方案为:

val tag = "LogTest"

private var debug = SwUtils.isDebug
private var propDebug = Log.isLoggable(tag, Log.DEBUG)

fun d(tag: String, msg: String) {
    if (debug || propDebug) {
        val t = if (tag.isBlank()) this.tag else tag
        Log.d(t, msg)
    }
}

通过参数来控制日志输出。

好处:Debug 模式下进行日志输出。

Release 模式下默认不输出日志。当需要日志时,终端下adb shell log.tag.LogTest DEBUG即可输出日志。

快速测试

接着上面的 setprop,可以自定义系统属性的key,value。那么在需要时就可以通过命令行终端修改系统属性,Android 程序读取该属性。

对于需要不断修改某个变量,重新构建打包安装测试的场景来说,可以节省大量的时间。

object SystemPropUtils {

    fun getProp(key: String): String {
        var result = ""
        try {
            val process = Runtime.getRuntime().exec("getprop log.tag.$key")
            result = process.inputStream.bufferedReader().readLine()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return result
    }
}

该方法可以读取 log.tag.key 的系统属性,需要修改时可以通过 adb shell setprop log.tag.key value 来设置,大大加快测试。

疑问:

adb shell setptop key value 。当 key 为任意值时会报错,有系统层开发的大神可以帮忙解决下这个疑问吗?

yunshuipiao avatar Dec 06 '19 09:12 yunshuipiao