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

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

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

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

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

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


当前回答

如果你可以运行全局替换(一次),然后保留一些编码惯例,你可以遵循Android框架中经常使用的模式。

而不是写作

Log.d(TAG, string1 + string2 + arg3.toString());

把它当作

if (BuildConfig.DEBUG) Log.d(TAG, string1 + String.format("%.2f", arg2) + arg3.toString());

现在proguard可以从优化版的DEX中删除StringBuilder和它使用的所有字符串和方法。使用proguard-android- optimization .txt,你就不用担心android.util了。

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

与Android Studio gradle插件,BuildConfig。DEBUG非常可靠,因此不需要额外的常数来控制剥离。

其他回答

最简单的方法;

使用DebugLog

当应用程序发布时,DebugLog会禁用所有日志。

https://github.com/MustafaFerhan/DebugLog

如果您不想弄乱额外的库或手动编辑代码,以下是我的解决方案。我创建了这个Jupyter笔记本来检查所有的java文件并注释掉所有的日志消息。虽然不完美,但它帮我完成了任务。

我建议在某个地方使用一个静态布尔值来指示是否记录日志:

class MyDebug {
  static final boolean LOG = true;
}

然后无论你想在哪里登录你的代码,只需要这样做:

if (MyDebug.LOG) {
  if (condition) Log.i(...);
}

现在,当你将MyDebug.LOG设置为false时,编译器将剔除这些检查中的所有代码(因为它是一个静态final,它在编译时知道代码没有被使用)。

对于较大的项目,您可能希望开始在单个文件中使用布尔值,以便能够根据需要轻松启用或禁用日志记录。例如,这些是我们在窗口管理器中拥有的各种日志常量:

static final String TAG = "WindowManager";
static final boolean DEBUG = false;
static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_ANIM = false;
static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_RESIZE = false;
static final boolean DEBUG_LAYERS = false;
static final boolean DEBUG_INPUT = false;
static final boolean DEBUG_INPUT_METHOD = false;
static final boolean DEBUG_VISIBILITY = false;
static final boolean DEBUG_WINDOW_MOVEMENT = false;
static final boolean DEBUG_ORIENTATION = false;
static final boolean DEBUG_APP_TRANSITIONS = false;
static final boolean DEBUG_STARTING_WINDOW = false;
static final boolean DEBUG_REORDER = false;
static final boolean DEBUG_WALLPAPER = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean HIDE_STACK_CRAWLS = true;
static final boolean MEASURE_LATENCY = false;

对应代码如下:

    if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
        TAG, "Adding window " + window + " at "
        + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");

linux下可以使用bash和sed删除日志:

find . -name "*\.java" | xargs sed -ri ':a; s%Log\.[ivdwe].*\);%;%; ta; /Log\.[ivdwe]/ !b; N; ba'

适用于多行日志。在这个解决方案中,您可以确定,日志不会出现在生产代码中。

克里斯托弗的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命令)