根据谷歌,我必须在发布我的Android应用程序谷歌播放之前“停用源代码中的Log方法的任何调用”。出版清单第3节节选:
在构建应用程序发布之前,请确保禁用了日志记录并禁用了调试选项。您可以通过删除源文件中对Log方法的调用来禁用日志记录。
我的开源项目很大,每次发布都要手动完成,这很痛苦。此外,删除Log行可能很棘手,例如:
if(condition)
Log.d(LOG_TAG, "Something");
data.load();
data.show();
如果注释Log行,则该条件将应用于下一行,并且可能不会调用load()。这样的情况是否罕见到我可以决定它不应该存在?
那么,是否有更好的源代码级方法来做到这一点呢?或者是一些聪明的ProGuard语法,有效但安全地删除所有Log行?
我发现一个更简单的解决方案是忘记所有的if检查,只是使用ProGuard剥离任何Log.d()或Log.v()方法调用时,我们调用我们的Ant发布目标。
通过这种方式,我们总是可以输出常规构建的调试信息,而不必对发布构建进行任何代码更改。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手册中的示例。
更新(4.5年后):现在我使用Timber进行Android日志记录。
它不仅比默认的Log实现更好一些(日志标记是自动设置的,很容易记录格式化的字符串和异常),而且您还可以在运行时指定不同的日志行为。
在这个例子中,日志语句只会在我的应用程序的调试版本中写入logcat:
木材是在我的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示例应用程序以获得更高级的示例,其中所有日志语句都在开发期间发送到logcat,在生产中,没有调试语句被记录,但错误会无声地报告给Crashlytics。
ProGuard将在你的发布版本中为你做这件事,现在来自android.com的好消息是:
http://developer.android.com/tools/help/proguard.html
ProGuard工具通过删除未使用的代码和用语义模糊的名称重命名类、字段和方法来缩小、优化和混淆代码。结果是一个更小的.apk文件,更难以进行反向工程。由于ProGuard使应用程序更难进行反向工程,因此当应用程序使用对安全性敏感的特性时,例如在应用程序授权时,使用它是很重要的。
ProGuard集成到Android构建系统中,所以你不需要手动调用它。ProGuard仅在以发布模式构建应用程序时运行,因此在以调试模式构建应用程序时不必处理混淆的代码。运行ProGuard是完全可选的,但强烈推荐。
本文档介绍如何启用和配置ProGuard,以及如何使用retrace工具解码混淆的堆栈跟踪
我在我的项目中使用了以下方法
创建自定义记录器类:
public class LoggerData
{
public static void showLog(String type, Object object) {
try {
Log.d("loggerData:" + type + "-", "showLog: " + new Gson().toJson(object));
} catch (Exception e) {
Log.d("TAG", "showLog: " + e.getLocalizedMessage());
Log.d("loggerData:" + type + "-", "showLog: " + object);
}
}
public static void showLog(Object object) {
try {
Log.d("loggerData:" + "-", "showLog: +" + new Gson().toJson(object));
} catch (Exception e) {
Log.d("TAG", "showLog: " + e.getLocalizedMessage());
Log.d("loggerData:" + "-", "showLog: " + object);
}
}
}
然后每当需要登录代码时,就像这样使用
LoggerData.showLog("Refreshed token: ", token);
在构建发布APK之前,在LoggerData类中只禁用一个地方的日志
例子
public class LoggerData {
public static void showLog(String type, Object object) {
try {
//Log.d("loggerData:" + type + "-", "showLog: " + new Gson().toJson(object));
} catch (Exception e) {
//Log.d("TAG", "showLog: " + e.getLocalizedMessage());
//Log.d("loggerData:" + type + "-", "showLog: " + object);
}
}
public static void showLog(Object object) {
try {
// Log.d("loggerData:" + "-", "showLog: +" + new Gson().toJson(object));
} catch (Exception e) {
//Log.d("TAG", "showLog: " + e.getLocalizedMessage());
//Log.d("loggerData:" + "-", "showLog: " + object);
}
}
}
希望它也能帮助到你。
我强烈建议使用Jake Wharton的Timber
https://github.com/JakeWharton/timber
它解决了您的问题,启用/禁用加添加标签类自动魔术
只是
public class MyApp extends Application {
public void onCreate() {
super.onCreate();
//Timber
if (BuildConfig.DEBUG) {
Timber.plant(new DebugTree());
}
...
日志将仅在调试版本中使用,然后使用
Timber.d("lol");
or
Timber.i("lol says %s","lol");
打印
“Your class / msg”,而不指定标签