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

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

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

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

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

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


当前回答

我想添加一些关于使用Proguard与Android Studio和gradle的精度,因为我有很多问题,从最终的二进制文件中删除日志行。

为了使保护工作中的副作用假设,有一个先决条件。

在你的gradle文件中,你必须指定proguard-android- optimization .txt作为默认文件。

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

        // With the file below, it does not work!
        //proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

实际上,在默认的proguard-android.txt文件中,通过以下两个标志禁用了优化:

-dontoptimize
-dontpreverify

proguard-android- optimization .txt文件没有添加这些行,所以现在假设副作用可以工作。

然后,就我个人而言,我使用SLF4J,特别是当我开发一些分发给其他人的库时。其优点是默认情况下没有输出。如果积分器想要一些日志输出,他可以使用Android的Logback并激活日志,这样日志就可以重定向到文件或LogCat。

如果我真的需要从最终库中剥离日志,我就会添加到我的Proguard文件中(当然是在启用了Proguard -android- optimization .txt文件之后):

-assumenosideeffects class * implements org.slf4j.Logger {
    public *** trace(...);
    public *** debug(...);
    public *** info(...);
    public *** warn(...);
    public *** error(...);
}

其他回答

我会考虑使用roboguice的日志记录工具,而不是内置的android.util.Log

它们的功能会自动禁用发布版本的调试和详细日志。 此外,您还可以免费获得一些漂亮的功能(例如,可定制的日志记录行为,每个日志的额外数据等等)

使用proguard可能是相当麻烦的,除非您有一个很好的理由(禁用日志不是一个好理由),否则我不会经历配置和使其与应用程序一起工作的麻烦。

这些都是很好的答案,但是当我完成我的开发时,我既不想在所有的Log调用周围使用if语句,也不想使用外部工具。

所以我使用的解决方案是用我自己的Log类替换android.util.Log类:

public class Log {
    static final boolean LOG = BuildConfig.DEBUG;

    public static void i(String tag, String string) {
        if (LOG) android.util.Log.i(tag, string);
    }
    public static void e(String tag, String string) {
        if (LOG) android.util.Log.e(tag, string);
    }
    public static void d(String tag, String string) {
        if (LOG) android.util.Log.d(tag, string);
    }
    public static void v(String tag, String string) {
        if (LOG) android.util.Log.v(tag, string);
    }
    public static void w(String tag, String string) {
        if (LOG) android.util.Log.w(tag, string);
    }
}

在所有的源文件中,我唯一要做的就是用我自己的类替换android.util.Log的导入。

我在我的项目中使用了以下方法

创建自定义记录器类:

public class LoggerData 
{
   
    public static void showLog(String type, Object object) {
        try {
            Log.d("loggerData:" + type + "-", "showLog: " + new Gson().toJson(object));
        } catch (Exception e) {
            Log.d("TAG", "showLog: " + e.getLocalizedMessage());
            Log.d("loggerData:" + type + "-", "showLog: " + object);
        }

    }

    public static void showLog(Object object) {
        
            try {
                Log.d("loggerData:" + "-", "showLog: +" + new Gson().toJson(object));
            } catch (Exception e) {
                Log.d("TAG", "showLog: " + e.getLocalizedMessage());
                Log.d("loggerData:" + "-", "showLog: " + object);
            }
        
    }
}

然后每当需要登录代码时,就像这样使用

  LoggerData.showLog("Refreshed token: ", token);

在构建发布APK之前,在LoggerData类中只禁用一个地方的日志

例子

public class LoggerData {
    

    public static void showLog(String type, Object object) {
        try {
            //Log.d("loggerData:" + type + "-", "showLog: " + new Gson().toJson(object));
        } catch (Exception e) {
            //Log.d("TAG", "showLog: " + e.getLocalizedMessage());
            //Log.d("loggerData:" + type + "-", "showLog: " + object);
        }

    }

    public static void showLog(Object object) {
       
            try {
              //  Log.d("loggerData:" + "-", "showLog: +" + new Gson().toJson(object));
            } catch (Exception e) {
                //Log.d("TAG", "showLog: " + e.getLocalizedMessage());
                //Log.d("loggerData:" + "-", "showLog: " + object);
            }
        }
    }

希望它也能帮助到你。

我发布的这个解决方案特别适用于Android Studio用户。我最近也发现了Timber,并通过以下方法成功地将其导入到我的应用程序中:

将最新版本的库放入build.gradle:

compile 'com.jakewharton.timber:timber:4.1.1'

然后在Android工作室,点击编辑->查找->替换路径…

输入Log。e(TAG,或任何您已经定义到“Text to find”文本框中的日志消息。然后你只需将其替换为timber。

单击“查找”,然后替换全部。

Android Studios现在将遍历项目中的所有文件,并将所有日志替换为木材。

我用这个方法遇到的唯一问题是,gradle之后会出现一百万个错误消息,因为它无法在每个java文件的导入中找到“Timber”。只需点击错误和Android工作室将自动导入“木材”到你的java。一旦你为所有的错误文件做了这些,gradle就会再次编译。

你还需要把这段代码放在你的Application类的onCreate方法中:

    if (BuildConfig.DEBUG) {
        Timber.plant(new Timber.DebugTree());
    }

这将导致只有当你处于开发模式而不是生产模式时才会出现应用日志记录。你也可以使用BuildConfig。RELEASE表示登录RELEASE模式。

正如zserge的评论所言,

Timber非常好,但如果你已经有一个现有的项目-你可以尝试github.com/zserge/log。它是android.util.Log的替代品,具有Timber的大部分功能,甚至更多。

他的日志库提供了简单的启用/禁用日志打印开关,如下所示。

此外,它只需要更改导入行,对于Log.d(…)不需要更改任何内容;声明。

if (!BuildConfig.DEBUG)
    Log.usePrinter(Log.ANDROID, false); // from now on Log.d etc do nothing and is likely to be optimized with JIT