Android 开发中一般会通过 BuildConfig.DEBUG 判断是否是 Debug 模式,从而做一些在 Debug 模式才开启的特殊操作,比如打印日志。这样好处是不用在发布前去主动修改,因为这个值在 Debug 模式下为 true,Release 模式下为 false。

1. 问题

如果应用只有一个 Module 没有问题,Debug 模式下 BuildConfig.DEBUG 会始终为 false。如果现在有两个 Module,分别为 App 和 Lib,且 App 依赖 Lib,在 Lib 内有工具类 LogUtils,代码如下:

当我们在 App Module 内调用 LogUtils 时我们会发现始终无法打印日志,因为上面的 BuildConfig.DEBUG 会始终为 false。为什么呢?

2. 原因

BuildConfig.java 是编译时自动生成的,并且每个 Module 都会生成一份,以该 Module 的 packageName 为 BuildConfig.java 的 packageName。所以如果你的应用有多个 Module 就会有多个 BuildConfig.java 生成,而上面的 Lib Module import 的是自己的 BuildConfig.java,编译时被依赖的 Module 默认会提供 Release 版给其他 Module 或工程使用,这就导致该 BuildConfig.DEBUG 会始终为 true。

3. 解决方案

根据上面分析的原因,目前我们有两个思路:

(1) 始终调用最终运行的 Module 的 BuildConfig,因为它没有被任何其他 Module 依赖,所以 BuildConfig.DEBUG 值会准确。

(2) 让被依赖的 Module 提供除 Release 版以外的其他版本。

3.1 解决方案一:使用其他的 BuildConfig.java

如果 Lib Module 中能够 import 到外层真正运行 App 的 BuildConfig 就 ok 了,如下:

通过反射得到真正执行的 Module 的 BuildConfig,在自己的 Application 内调用:

AppUtils.syncIsDebug(getApplicationContext());

这样看起来达到目的了。

但仔细看看会发现这种解决方案还是有问题,因为 BuildConfig.java 的 packageName 是 Module 的 Package Name,即 AndroidManifest.xml 中的 package 属性,而 context.getPackageName() 得到的是应用的 applicationId,这个 applicationId 通过 build.gradle 是可以修改的。所以当 build.gradle 中的 applicationId 与 AndroidManifest.xml 中的 package 属性不一致时,上面的反射查找类路径便会出错。

PS:这种方案还有个变种就是通过 android.app.ActivityThread.currentPackageName 得到包名,从而省去传递 Context 初始化的步骤,但依然有 applicationId 被修改后类查找不到类似的问题。

3.2 解决方案二:Lib publishNonDefault

让被依赖的 Module 提供除 Release 版以外的其他版本,这种方案需要将所有被依赖 library 中添加:

android {

publishNonDefault true

}

表示该 Module 不使用默认配置,这样会同时打包其他版本,包括 Debug 版。另外需要在 App Module 中将其依赖的 library 如下逐个添加:

dependencies {

releaseCompile project(path: ':library', configuration: 'release')

debugCompile project(path: ':library', configuration: 'debug')

}

表示依赖不同版本的依赖 Module。

然而这种方式所有 Module 配置都需要修改,侵入性太强。

3.3 最终解决方案:使用 ApplicationInfo.FLAG_DEBUGGABLE

既然 BuildConfig 的方式行不通,我们反编译 Debug 包和 Release 包对比看看有没有其他的区别,会发现他们 AndroidManifest.xml 中 application 节点的 android:debuggable 值是不同的。Debug 包值为 false,Release 包值为 true,这是编译自动修改的。所以我们考虑通过 ApplicationInfo 的这个属性去判断是否是 Debug 版本,如下:

在自己的 Application 内调用进行初始化,

AppUtils.syncIsDebug(getApplicationContext());

这样以后调用 AppUtils.isDebug() 即可判断是否是 Debug 版本,比如在上面的 LogUtils 中。同时适用于 Module 是 Lib 和 applicationId 被修改的情况,比 BuildConfig.DEBUG 靠谱的多。

这个方案有个注意事项就是自己 App Module 中不能主动设置 android:debuggable,否则无论 Debug 还是 Release 版会始终是设置的值。当然本身就没有自动设置的必要。

解决依赖的moduleBuildConfig.DEBUG总是未false的问题的更多相关文章

  1. [错误解决]Ubuntu中使用dpkg安装deb文件提示依赖关系问题,仍未被配置

    使用dpkg进行软件安装时,提示:dpkg:处理软件包XXX时出错:依赖关系问题,仍未被配置 使用如下命令,sudo apt-get install -f 等分析完之后,重新使用dpkg –i XXX ...

  2. 升级python2至python3解决依赖关系

    1.最小化安装centos7,在升级python3的时候会出现很多包未安装,为解决依赖关系: yum -y install gcc gcc-c++ zlib zlib-devel libffi-dev ...

  3. 使用ReflectionTestUtils解决依赖注入

    概述   当使用junit来测试Spring的代码时,为了减少依赖,需要给对象的依赖,设置一个mock对象,但是由于Spring可以使用@Autoware类似的注解方式,对私有的成员进行赋值,此时无法 ...

  4. ASP.NET MVC 解决LINQ表达式中的SqlMethods 未找到命名空间问题

    右键项目属性下的引用: 添加引用: 搜索寻找——System.Data.Linq,然后添加成功,即可解决LINQ表达式中的SqlMethods 未找到命名空间问题

  5. (转)Ubuntu中使用dpkg安装deb文件提示依赖关系问题,仍未被配置

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5638149.html 参考网址: http://zhidao.baidu.com/link?url=b ...

  6. 解决mac 10.11 以后 无法使用未签名第三驱动

    解决 最新版 mac 系统 无法使用未签名第三驱动 10.12.多 我的情况是 10.11.4 Beta (15E27e) 使用绿联usb网卡不正常. 下面的命令为检测驱动是否装载的一些命令.sudo ...

  7. 搭建php环境时解决jpeg6 make: ./libtool:命令未找到

    搭建php环境时解决jpeg6 make: ./libtool:命令未找到 [root@bogon jpeg-6b]# make; make install ./libtool --mode=comp ...

  8. 使用google wire解决依赖注入

    使用google wire解决依赖注入 google wire是golang的一个依赖注入解决的工具,这个工具能够自动生成类的依赖关系. 当我们写代码的时候,都希望,类都是一个个独立的结构,互不耦合, ...

  9. 【maven】maven查看项目依赖并解决依赖冲突的问题

    一.问题 项目开发过程中,经常会遇到jar冲突,然后maven根据自己的规则进行冲突解决,导致项目在运行的过程中报错. 1.maven自动解决依赖冲突的规则是什么? 2.如何查看当前项目的maven的 ...

随机推荐

  1. Majority Element问题---Moore's voting算法

    Leetcode上面有这么一道难度为easy的算法题:找出一个长度为n的数组中,重复次数超过一半的数,假设这样的数一定存在.O(n2)和O(nlog(n))(二叉树插入)的算法比较直观.Boyer–M ...

  2. 主机 & 虚拟机 & 开发板 相互通信

    @2018年7月10日 成功方法之一: 虚拟机设置为桥接模式,保证三者在同一网段,ping方式测试网络连通性OK

  3. 【ARC076D/F】Exhausted?

    Description ​ 题目链接 Solution ​ 场上尝试使用优化建图网络流实现,结果T到怀疑人生. ​ 鉴于这是个匹配问题,考虑用贪心做一下. ​ 先退一步,想一下如果每一个人只有\([1 ...

  4. POJ 3281 Dining (网络流)

    POJ 3281 Dining (网络流) Description Cows are such finicky eaters. Each cow has a preference for certai ...

  5. c++并发编程之创建线程

    以boost为例.boost::thread有两个构造函数: (1)thread():构造一个表示当前执行线程的线程对象: (2)explicit thread(const boost::functi ...

  6. 界面编程之QT的文件操作20180729

    /*******************************************************************************************/ 一.QT文件 ...

  7. 在windows上部署使用Redis出现问题的解决方法

    下载Redis 在Redis的官网下载页上有各种各样的版本,我这次是在windows上部署的,要去GitHub上下载.目前的是2.8.12版的,直接解压,在\bin\release 目录下有个压缩包, ...

  8. Kubernetes HPA

    简介 通过手工执行 kubectl scale 命令或者通过修改deployment的replicas数量,可以实现 Pod 扩容或缩容.但如果仅止于此,显然不符合 Google 对 Kubernet ...

  9. ELKStack-生产案例项目实战(十一)

    ELKStack-生产案例项目实战 1.收集ES和apache日志,入redis input { file { path => "/etc/httpd/logs/access_log& ...

  10. Java 调用 groovy 脚本文件,groovy 访问 MongoDB

    groovy 访问 MongoDB 示例: shell.groovy package db import com.gmongo.GMongoClient import com.mongodb.Basi ...