如何在构建Android应用程序的发布版本之前删除所有调试日志记录调用?

随声附和 提交于 2020-02-26 11:26:03

根据谷歌的说法, 在将我的Android应用程序发布到Google Play之前,我必须“ 停用对源代码中任何Log方法的调用 ”。 摘录自出版物清单的第3部分:

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

我的开源项目很大,每次发布时手动执行都很痛苦。 此外,删除日志行可能很棘手,例如:

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

如果我对日志行进行注释,则条件适用于下一行,并且可能不会调用load()。 这种情况是否足够罕见,我可以决定它不应该存在?

那么,是否有更好的源代码级方法呢? 或者可能有一些聪明的ProGuard语法可以有效但安全地删除所有日志行?


#1楼

ProGuard将在您的发布版本上为您完成,现在来自android.com的好消息:

http://developer.android.com/tools/help/proguard.html

ProGuard工具通过删除未使用的代码并使用语义模糊的名称重命名类,字段和方法来缩小,优化和混淆代码。 结果是较小的.apk文件,更难以进行逆向工程。 由于ProGuard使您的应用程序更难以进行逆向工程,因此当您的应用程序使用对安全性敏感的功能(例如,在许可您的应用程序时)时,使用它非常重要。

ProGuard已集成到Android构建系统中,因此您无需手动调用它。 只有在发布模式下构建应用程序时,ProGuard才会运行,因此在调试模式下构建应用程序时,不必处理混淆代码。 ProGuard运行是完全可选的,但强烈建议。

本文档介绍了如何启用和配置ProGuard以及使用回扫工具解码混淆的堆栈跟踪


#2楼

我使用了像Google IO示例应用程序中的LogUtils类。 我将其修改为使用特定于应用程序的DEBUG常量而不是BuildConfig.DEBUG,因为BuildConfig.DEBUG不可靠 。 然后在我的课程中我有以下内容。

import static my.app.util.LogUtils.makeLogTag;
import static my.app.util.LogUtils.LOGV;

public class MyActivity extends FragmentActivity {
  private static final String TAG = makeLogTag(MyActivity.class);

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    LOGV(TAG, "my message");
  }
}

#3楼

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

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

默认方法isLoggable(...)返回false,只有在设备中的setprop之后才会这样:

adb shell setprop log.tag.MyAppTag DEBUG

这意味着可以打印任何DEBUG级别以上的日志。 参考android doc:

检查指定标记的日志是否可以在指定级别进行记录。 任何标记的默认级别都设置为INFO。 这意味着将记录任何级别以上且包括INFO。 在对日志记录方法进行任何调用之前,应检查是否应记录您的标记。 您可以通过设置系统属性来更改默认级别:'setprop log.tag。 '级别是VERBOSE,DEBUG,INFO,WARN,ERROR,ASSERT或SUPPRESS。 SUPPRESS将关闭标签的所有日志记录。 您还可以创建一个local.prop文件,其中包含以下内容:'log.tag。='并将其放在/data/local.prop中。

所以我们可以使用自定义日志工具:

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);
    }
}

#4楼

Christopher的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命令)


#5楼

我建议在某处使用静态布尔值来指示是否记录:

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 + ")");
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!