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

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

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

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

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

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


当前回答

这就是我过去在我的android项目上所做的。

在Android Studio我们可以做类似的操作,Ctrl+Shift+F从整个项目(命令+Shift+F在MacOs)和Ctrl+Shift+R替换((命令+Shift+R在MacOs))

其他回答

这些都是很好的答案,但是当我完成我的开发时,我既不想在所有的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的导入。

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

TAG总是类名

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

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

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

这就是我过去在我的android项目上所做的。

在Android Studio我们可以做类似的操作,Ctrl+Shift+F从整个项目(命令+Shift+F在MacOs)和Ctrl+Shift+R替换((命令+Shift+R在MacOs))

正如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

我发现一个更简单的解决方案是忘记所有的if检查,只是使用ProGuard剥离任何Log.d()或Log.v()方法调用时,我们调用我们的Ant发布目标。

通过这种方式,我们总是可以输出常规构建的调试信息,而不必对发布构建进行任何代码更改。ProGuard还可以对字节码进行多次传递,以删除其他不需要的语句和空块,并可以在适当的地方自动内联短方法。

例如,这是一个非常基本的Android ProGuard配置:

-dontskipnonpubliclibraryclasses
-dontobfuscate
-forceprocessing
-optimizationpasses 5

-keep class * extends android.app.Activity
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
}

因此,您可以将其保存到一个文件中,然后从Ant调用ProGuard,传入刚刚编译的JAR和正在使用的Android平台JAR。

请参见ProGuard手册中的示例。


更新(4.5年后):现在我使用Timber进行Android日志记录。

它不仅比默认的Log实现更好一些(日志标记是自动设置的,很容易记录格式化的字符串和异常),而且您还可以在运行时指定不同的日志行为。

在这个例子中,日志语句只会在我的应用程序的调试版本中写入logcat:

木材是在我的Application onCreate()方法中设置的:

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

然后在我的代码中的其他地方,我可以很容易地记录:

Timber.d("Downloading URL: %s", url);
try {
  // ...
} catch (IOException ioe) {
  Timber.e(ioe, "Bad things happened!");
}

请参阅Timber示例应用程序以获得更高级的示例,其中所有日志语句都在开发期间发送到logcat,在生产中,没有调试语句被记录,但错误会无声地报告给Crashlytics。