根据谷歌的说法,在将我的Android应用发布到Google Play之前,我必须"deactivate any calls to Log methods in the source code".摘自publication checklist页第3节:

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

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

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

如果我对日志(log)行进行注释,那么该条件将应用于下一行,很可能不会调用load().这种情况是否足够罕见,以至于我可以决定它不应该存在?

那么,有没有更好的源代码级方法来实现这一点?或者使用一些聪明的ProGuard语法来高效但安全地删除所有日志(log)行?

推荐答案

我发现一个简单得多的解决方案是,当我们调用Ant release目标时,忘记所有的if个判断,只使用ProGuardgo 除所有Log.d()Log.v()个方法调用.

这样,我们总是可以为常规版本输出调试信息,而不必对发布版本进行任何代码更改.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手册中的the examples.


Update (4.5 years later):现在我用Timber来记录Android.

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

在此示例中,日志(log)记录语句将仅在我的应用程序的调试版本中写入logcat:

木材采用my 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 sample app,其中所有日志(log)语句都在开发期间发送到logcat,并且在生产中不记录调试语句,但错误会自动报告给Crashlytics.

Android相关问答推荐

如何在Jetpack导航中不显示目的地?

在命令行Android应用程序开发中苦苦挣扎

如何从Android 12的来电中获取电话号码?

在Delphi中使用OpenCV for Android在使用JLIST时抛出错误

从惰性列中删除项目时Jetpack Compose崩溃

Android布局渲染问题

如何用帆布在喷气背包中画一个圆环?

为什么我在 android 中使用 TabLayout 时无法启动我的 Activity?

Jetpack Compose 使用 SavedStateHandle 发送返回结果不适用于 ViewModel 中注入的 SavedStateHandle

在 MVVM Jetpack Compose 上添加依赖项时出现重复类错误

setContentView() 方法的签名

如何添加到先前预填充的 Room 数据库?

如何在 Jetpack Compose 中设置行宽等于 TextField 的宽度?

Android 12 通过包管理器中断 APK 安装?

如何授予对 Uri 图像的永久权限(androidx)

复用 RecyclerView 适配器,避免不必要的 API 调用

使 Compose LazyColumn 的最后一项填满屏幕的其余部分

如何在不使用 NestedScrollView 的情况下使用带有 CollapsingToolbar 的 ViewPager?

为什么使用 React Native 和 expo 创建的 APK 体积这么大?

在delphi中将Jnet_uri转换为Tbitmap