根据谷歌,我必须在发布我的Android应用程序谷歌播放之前“停用源代码中的Log方法的任何调用”。出版清单第3节节选:

在构建应用程序发布之前,请确保禁用了日志记录并禁用了调试选项。您可以通过删除源文件中对Log方法的调用来禁用日志记录。

我的开源项目很大,每次发布都要手动完成,这很痛苦。此外,删除Log行可能很棘手,例如:

if(condition)
  Log.d(LOG_TAG, "Something");
data.load();
data.show();

如果注释Log行,则该条件将应用于下一行,并且可能不会调用load()。这样的情况是否罕见到我可以决定它不应该存在?

那么,是否有更好的源代码级方法来做到这一点呢?或者是一些聪明的ProGuard语法,有效但安全地删除所有Log行?


当前回答

我有一个很简单的解决办法。我使用IntelliJ进行开发,因此细节有所不同,但这个想法应该适用于所有IDE。

我选择我的源树的根,右键单击并选择“替换”。然后我选择将所有“Log.”替换为“//Log.”。这将删除所有日志语句。为了稍后将它们放回去,我重复相同的替换,但这次将所有“//Log.”替换为“Log.”。

对我来说太好了。只需记住将replace设置为区分大小写,以避免出现“Dialog.”之类的意外。为了获得额外的保证,您还可以使用“Log.”作为要搜索的字符串执行第一步。

辉煌。

其他回答

如果您希望使用编程方法而不是使用ProGuard,那么通过创建自己的类,其中包含两个实例(一个用于调试,一个用于发布),您可以选择在任何一种情况下登录什么。

所以,如果你不想在发布时记录任何东西,只需实现一个什么都不做的Logger,如下例所示:

import android.util.Log

sealed class Logger(defaultTag: String? = null) {
    protected val defaultTag: String = defaultTag ?: "[APP-DEBUG]"

    abstract fun log(string: String, tag: String = defaultTag)

    object LoggerDebug : Logger() {
        override fun log(string: String, tag: String) {
            Log.d(tag, string)
        }
    }

    object LoggerRelease : Logger() {
        override fun log(string: String, tag: String) {}
    }

    companion object {
        private val isDebugConfig = BuildConfig.DEBUG

        val instance: Logger by lazy {
            if(isDebugConfig)
            LoggerDebug
            else
                LoggerRelease
        }

    }
}

然后使用记录器类:

class MainActivity : AppCompatActivity() {

private val logger = Logger.instance

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    logger.log("Activity launched...")
    ...
    myView.setOnClickListener {
        ...

        logger.log("My View clicked!", "View-click")
    }
}

== update ==

如果我们想避免字符串连接以获得更好的性能,我们可以添加一个带有lambda的内联函数,该函数只在调试配置中调用:

// Add this function to the Logger class.
inline fun commit(block: Logger.() -> Unit) {
    if(this is LoggerDebug)
        block.invoke(this)
}

然后:

 logger.commit {
     log("Logging without $myVar waste of resources"+ "My fancy concat")
 }

因为我们使用的是内联函数,所以没有额外的对象分配,也没有额外的虚方法调用。

我的方法:

1)启用列选择模式(alt+shift+insert)

2)选择一个日志。d(标签,“文本”);“日志”部分。

3)然后按shift + CTRL + Alt + j

4)点击左箭头

分离完成

6)点击删除。

这将一次性删除java文件中的所有LOG调用。

我喜欢使用Log。d(TAG,一些字符串,通常是字符串。格式())。

TAG总是类名

改变日志。d(TAG,——> Logd(在类的文本中

private void Logd(String str){
    if (MainClass.debug) Log.d(className, str);
}

通过这种方式,当您准备发布版本时,将MainClass.debug设置为false!

Per android.util.Log提供了一种启用/禁用日志的方法:

public static native boolean isLoggable(String tag, int level);

默认情况下,isLoggable(…)方法返回false,只有在你在设备中设置prop后,像这样:

adb shell setprop log.tag.MyAppTag DEBUG

这意味着DEBUG级别以上的任何日志都可以打印出来。参考android文档:

Checks to see whether or not a log for the specified tag is loggable at the specified level. The default level of any tag is set to INFO. This means that any level above and including INFO will be logged. Before you make any calls to a logging method you should check to see if your tag should be logged. You can change the default level by setting a system property: 'setprop log.tag. ' Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will turn off all logging for your tag. You can also create a local.prop file that with the following in it: 'log.tag.=' and place that in /data/local.prop.

所以我们可以使用自定义log util:

public final class Dlog 
{
    public static void v(String tag, String msg)
    {
        if (Log.isLoggable(tag, Log.VERBOSE))
            Log.v(tag, msg);
    }

    public static void d(String tag, String msg)
    {
        if (Log.isLoggable(tag, Log.DEBUG))
            Log.d(tag, msg);
    }

    public static void i(String tag, String msg)
    {
        if (Log.isLoggable(tag, Log.INFO))
            Log.i(tag, msg);
    }

    public static void w(String tag, String msg)
    {
        if (Log.isLoggable(tag, Log.WARN))
            Log.w(tag, msg);
    }

    public static void e(String tag, String msg)
    {
        if (Log.isLoggable(tag, Log.ERROR))
            Log.e(tag, msg);
    }
}

克里斯托弗的Proguard解决方案是最好的,但如果因为任何原因你不喜欢Proguard,这里有一个非常低技术含量的解决方案:

评论日志:

find . -name "*\.java" | xargs grep -l 'Log\.' | xargs sed -i 's/Log\./;\/\/ Log\./g'

取消日志:

find . -name "*\.java" | xargs grep -l 'Log\.' | xargs sed -i 's/;\/\/ Log\./Log\./g'

一个限制是您的日志记录指令不能跨越多行。

(在项目根的UNIX shell中执行这些行。如果使用Windows,请使用UNIX层或使用等效的Windows命令)