前言
在Android 应用程序开发中,不可避免地会常常输出各种调试信息,通常我们会使用android.util.Log类输出该类日志信息(这是推荐使用的方式)。然而,在项目发布的时候,我们常常需要关闭这些冗余的Log信息,手工关闭Log相当不方便,而且容易出现遗漏。
一种解决方案
package org.flyingcat.util;import android.util.Log;/** * @author Flyingcat * @create 2014-4-23 * @version 1.0 */public class AppLog { private static final boolean LOG_DEBUG = true; public void d(String tag, String msg){ if (LOG_DEBUG){ Log.i(tag, msg); } } //省略重载方法……}
这里展示了一种解决方案。这实际上是对标准Log的一个简单包装,在正式发布之前仍然需要手工将LOG_DEBUG变量的值设置为false,频繁发布的时候比较麻烦。
ADT的新特性
ADT 17.0.0以上版本在Build之后,会在R.java的相同路径下生成一个叫做BuildConfig.java的文件,内容非常简单:
/** Automatically generated file. DO NOT MODIFY */package org.flyingcat.androidcodelib;public final class BuildConfig { public final static boolean DEBUG = true;}
在ADT的更新说明中是这样写的:
Added a feature that allows you to run some code only in debug mode.Builds now generate a class called BuildConfig containing a DEBUGconstant that is automatically set according to your build type.You can check the (BuildConfig.DEBUG) constant in your code to run debug-only functions.
大意是:
ADT17添加了一个新的特性,允许开发者仅在debug模式运行某些代码。每次Build的时候会新生成一个BuildConfig类,包含一个DEBUG常量,这个常量会在Build的时候根据Build类型自动生成。你可以在代码中测试(BuildConfig.DEBUG)常量来执行仅应在debug模式执行的代码。
但实际上,有些时候并不能达到效果,为什么呢?
很显然,我们可能使用方法不对。
如何确保关闭Log
既然Build的时候根据Build类型自动生成BuildConfig类,从Eclipse的Project的菜单中可以看出来,分为手动和自动两种类型:
默认情况下,使用Eclipse生成的项目中bin目录下的.apk文件,无论Build模式为哪种,DEBUG字段始终为true。这主要是由于Eclipse使用的是默认的android调试签名debug.keystore,这个签名被限制为debug mode,因此和release mode 的签名略有不同。
但是,这并不是说使用Android Tools->Export Signed Application Package生成的.apk就是release mode!之前我记得我看的某些博客中讲,只要使用AndroidTools导出的,DEBUG常量的值都是false,这是非常不正确和不负责任的,为此我还在客户面前闹过笑话::>_<::。【好吧你们知道我为什么要写这个了】
经过多次测试,如果使用的是自动build,在签名导出的时候生成的.apk很可能仍然是debug mode,即使是手动Build,偶尔也会出现这种情形【我使用的ADT版本为 22.3.0】。为了确保自己的.apk是release mode,建议每次发布的时候按照下列步骤执行:
取消自动Build;
Clean(会丢弃所有编译好的状态);
Export Signed Application Package.
有人说第三步应该是Build,之后才是Export,但导出的时候实际上会重新Build一次。一个明显的例子是在Clean之后gen包变空了,但是执行Export之后它的内容又回来了。因此我认为可以略去这一步。
可以使用一个简单的App测试发布方式是否为debug模式,其主要代码如下。由于篇幅所限,这里不贴出运行截图,有需要的同学可以在文末地址免费下载任意调戏,别玩坏了:-)。
//省略包声明、导入语句public class MainActivity extends Activity { private static final String LOG_TAG = "MainActivity"; private TextView textview; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.i(LOG_TAG, "Hello, Flyingcat."); textview = (TextView) findViewById(R.id.textView1); if (BuildConfig.DEBUG){ textview.setText("This release is debug mode!"); } else{ textview.setText("This release is not debug mode."); } }}
附测试应用下载地址: