记一次BuildConfig.DEBUG不准确导致的Bug

Android开发过程中通常我们区分debug和release的相关配置都会采用BuildConfig.DEBUG来进行判断,殊不知这个东西弄不好却是一个坑,刚好在最近的开发过程中遇到。

问题

最近在负责一个内部系统,需要根据BuildConfig.DEBUG来判断相关入参,debug模式主要供QA进行demo环境测试,release模式主要用于模拟线上真实环境和回归。但是发现,无论怎么调,BuildConfig.DEBUG始终都是true,也就是release模式下还是true,这就属于bug了,这个问题必须要解决的,因为项目中使用BuildConfig.DEBUG还是很频繁。

分析

再找不到任何头绪的时候开始google和baidu,发现均是BuildConfig.DEBUG始终为false的问题,刚好和我遇到的这个相反,并且一篇文章满天飞,很是费解。

我开始研究他们的原因,有两种说法:

  1. 当项目中有很多module时并且有很多相互依赖,编译的时候因为每个module都会生成一个BuildConfig文件,因为相互依赖,这些BuildConfig都可以看到,也就是说,有可能你导包导错了,导入不是自己当前模块下的BuildConfig。但是这种几乎也不会出错,因为编译的时候所有的module都是跟随编译环境更换debug模式或者release模式,除非你在哪里做了骚操作,把被依赖的那个module下的BuildConfig.DEBUG值改掉了。
  2. 在调试代码时因为Build Variants在debug模式和release模式间进行切换,编译器没有及时同步Gradle,导致BuildConfig.DEBUG的值没能更改。当然这种情况也不太容易发生,如果Gradle一直不同步那我们的编译环境也会出现问题。

最终原因

经过上边的两种情况都进行了验证,并且都淘汰掉了。接下来我在build.gradle下buildTypes下查找时忽然发现一个字段debuggable true,debug和release模式的配置都是这个。
buggable配置

开始怀疑,通过google查清,debuggable主要用于应用在当前编译模式下是否可以进行调试。以下是引用官方的说明:

Whether or not the application can be debugged, even when running on a device in user mode — “true” if it can be, and “false” if not. The default value is “false”.

这个字段就是引发此次Bug的罪魁祸首,他可以直接影响BuildConfig.DEBUG和ApplicationInfo.FLAG_DEBUGGABLE的值,并且是等同的。

debuggable除了可以配置在gradle中,也可以配置在manifest的application的闭包中,gradle中配置不会提醒报错或警告,但是在manifest中配置直接“报红”了:
manifest中配置debuggable报红

google并不建议我们进行这样设置:

Avoid hardcoding the debug mode; leaving it out allows debug and release builds to automatically assign one less…

It’s best to leave out the android:debuggable attribute from the manifest. If you do, then the tools will automatically insert android:debuggable=true when building an APK to debug on an emulator or device. And when you perform a release build, such as Exporting APK, it will automatically set it to false.

If on the other hand you specify a specific value in the manifest file, then the tools will always use it. This can lead to accidentally publishing your app with debug information.

随便翻译了一下,大概以下两种原因:

  1. 硬编码导致所有的编译环境不能覆盖,debug和release模式都是相同的值。
  2. 会影响项目中的BuildConfig.DEBUG导致在release会把一些私密信息打印出来,如果用这种方式去判断和设置值,说不定会出现一些严重的bug,像我开篇遇到的那样。

总结

到此针对BuildConfig.DEBUG值不准确的原因终于弄清楚了。
总之我们在开发中一定要注意以下几点:

  1. 在多模块相互依赖的情况下,api调用导包一定要导正确。
  2. 不要随便在gradle或者manifese中设置debuggable的值。
  3. 如果在gradle中真的需要配置debuggable,可以自己额外再创造一个字段,区分debug和release环境,例如:
    在release模式下:
    buildConfigField("boolean", "IS_DEBUG", "false")
    
    在debug模式下:
    buildConfigField("boolean", "IS_DEBUG", "true")
    
    然后在项目中直接引用BuildConfig.IS_DEBUG即可,这样始终是准确的。

参考

  • https://developer.android.com/guide/topics/manifest/application-element
  • https://stackoverflow.com/questions/45637524/buildconfig-debug-vs-applicationinfo-flag-debuggable
  • https://www.trinea.cn/android/android-whether-debug-mode-why-buildconfig-debug-always-false/
发布了47 篇原创文章 · 获赞 38 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/li0978/article/details/105336173