【问题标题】:Should I comment my log calls when creating my final package?我应该在创建最终包时评论我的日志调用吗?
【发布时间】:2011-06-24 22:29:54
【问题描述】:

我有一个使用大量Log.d() 或Log.e() 调用进行调试的应用程序。现在我想创建我的最终发布包。 Eclipse 的 Android 导出功能提到要删除清单中的 "Debuggable" 标志,我已经这样做了。我是否还应该评论所有Log 调用以提高我的应用程序的性能,或者这些调用在不可调试的最终版本包中什么都不做?

【问题讨论】:

    标签: android android-log


    【解决方案1】:

    我已将 Log 类子类化为一个名为 Trace 的类,它反映了 Log 上的方法。所以我执行 Trace.d(TAG,"blah") 然后在 Trace.d 方法中,代码仅基于名为 LOGGING_LEVEL 的静态最终类变量执行,该变量具有 1-5 级(无,仅错误,错误和警告,错误和警告和信息,以及包括调试在内的所有内容)。在生成生产 APK 时,Proguard 会删除应用程序中未使用的所有代码,因此它会为我完成。

    对我来说,日志记录太重要了,无法从源中删除,但出于性能、安全和知识产权原因,必须从生产应用程序中删除它。

    这种结构允许我向应用程序添加更多的日志记录,这使得调试问题变得更加容易,但对生产 APK 没有任何影响

    public class Trace
    {
        public static final int    NONE                         = 0;
        public static final int    ERRORS_ONLY                  = 1;
        public static final int    ERRORS_WARNINGS              = 2;
        public static final int    ERRORS_WARNINGS_INFO         = 3;
        public static final int    ERRORS_WARNINGS_INFO_DEBUG   = 4;
    
        private static final int          LOGGING_LEVEL   = ERRORS_ONLY;        // Errors + warnings + info + debug (default)
    
        public static void e(String tag, String msg)
        {
            if ( LOGGING_LEVEL >=1) Log.e(tag,msg);
        }
    
        public static void e(String tag, String msg, Exception e)
        {
            if ( LOGGING_LEVEL >=1) Log.e(tag,msg,e);
        }
    
        public static void w(String tag, String msg)
        {
            if ( LOGGING_LEVEL >=2) Log.w(tag, msg);
        }
    
        public static void i(String tag, String msg)
        {
            if ( LOGGING_LEVEL >=3) Log.i(tag,msg);
        }
    
        public static void d(String tag, String msg)
        {
            if ( LOGGING_LEVEL >=4) Log.d(tag, msg);
        }
    
    }
    

    【讨论】:

    • 我以为这已经包含在Android的Log类中了。为什么我们不能只做 Log.setLogLevel(Log.ERROR)?如果不是,您的解决方案似乎真的很好。
    • “对生产 APK 没有任何影响”......错误。这是一个众所周知的反模式。问题在于,无论您是否实际记录消息,总是会评估 msg 参数。例如 Trace.e("blah", "error was: " + error.getCode() + ", ruh roh!")。无论您是否登录,都会创建三个临时字符串 obj 和两个多余的方法调用。
    • @jmbouffard Log 上没有名为 setLogLevel() 的方法
    • 唯一的方法是用 if 包装每个日志语句: if (Log.getLevel() > Log.DEBUG) then Log.d(...);那么你做的最糟糕的是一个简单的类型比较。它产生了一些非常非常难看的代码。另一种选择是在编译时应用一些 AOP 解决方案来注入或不注入日志语句。但是,我没有在 android 环境中应用它的经验。
    • @OneWorld 所有日志记录工具都有一个“获取日志级别”方法,可以按照我的建议使用。
    【解决方案2】:

    这让我检查了我的假设,即如果没有在清单中设置可调试标志,代码中的 log.d 行将不会出现在签名的发布 apk 上,我错了,它们仍然出现.

    对 SO 的快速搜索使我得到了这个问题的公认答案: Remove all debug logging calls before publishing: are there tools to do this?

    效果很好,您无需更改任何代码。

    【讨论】:

    • 似乎是一个不错的解决方案,但我不确定是否要使用 Proguard。
    • @jmbouffard:如果您已经在使用 Ant 构建您的发布 apk,那么添加 Proguard 非常简单,因为 SDK 的 main_rules.xml 中已经有一个目标。如果你不熟悉 Ant,那么我同意,这可能会有点痛苦。
    【解决方案3】:

    来自 developer.android.com:

    关闭日志记录和调试并清理数据/文件对于发布,您 应确保调试设施 被关闭并且调试和 其他不必要的数据/文件是 从您的应用程序项目中删除。

    删除 android:debuggable="true" 属性来自 清单的元素。删除日志 文件、备份文件和其他 应用程序中不必要的文件 项目。检查私人或 专有数据并将其删除为 必要的。停用任何对 Log 的调用 源代码中的方法。

    Source

    【讨论】:

    • 我不会那么严格地删除所有日志记录,但肯定会调试日志记录。
    • 我已经在 android dev 网站上看到了该信息,但我不清楚除了评论所有内容之外是否有“关闭日志记录”的机制。此外,当他们说“在源代码中停用对 Log 方法的任何调用”时,不清楚他们的意思是“评论”还是有其他方式。
    • 我想知道这是什么伪君子写的? android 日志中包含 98% 的来自库存 android 应用程序和服务的消息。也许他们的意思是“禁用所有日志记录,这样当我们想要查找日志消息时它就不会弄乱日志。”
    【解决方案4】:

    我会删除如下的日志记录代码:

    -assumenosideeffects class android.util.Log {
        public static boolean isLoggable(java.lang.String, int);
        public static int v(...);
        public static int i(...);
        public static int w(...);
        public static int d(...);
        public static int e(...);
        public static java.lang.String getStackTraceString(java.lang.Throwable);
    }
    
    -assumenosideeffects class java.lang.Exception {
        public void printStackTrace();
    }
    
    -assumenosideeffects class * implements org.slf4j.Logger {
        public void trace(...);
        public void debug(...);
        public void info(...);
        public void warn(...);
        public void error(...);
        public boolean isTraceEnabled(...);
        public boolean isDebugEnabled(...);
        public boolean isInfoEnabled(...);
        public boolean isWarnEnabled(...);
        public boolean isErrorEnabled(...);
    }
    

    如果需要,可以保留错误和警告类别。但请确保只有在代码删除生效时才为构建启用优化和收缩

    【讨论】:

      猜你喜欢
      • 2014-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-22
      • 1970-01-01
      相关资源
      最近更新 更多