根据谷歌的说法, 在将我的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 + ")");
来源:oschina
链接:https://my.oschina.net/stackoom/blog/3166855