16

When looking at the BuildConfig class generated by Android Studio and the Gradle plugin one can see that the BuildConfig.DEBUG field is initialized using the Boolean.parseBoolean(String) call instead of using one of the boolean literals true or false.

When I add custom build properties using Gradle I would simply do it like this:

android {
    buildTypes.debug.buildConfigField 'boolean', 'SOME_SETTING', 'true'
}

But looking at the generated BuildConfig tells me that Google has taken a different approach with the DEBUG flag:

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");

  // more fields here

  // Fields from build type: debug
  public static final boolean SOME_SETTING = true;
}

What is the benefit of using Boolean.parseBoolean(String) instead of literals?

david.schreiber
  • 3,851
  • 2
  • 28
  • 46
  • 7
    You asked the question and answered it the same second? Achievement unlocked. Claim your superhuman badge. – Rajesh Apr 27 '15 at 06:58
  • http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ – david.schreiber Apr 27 '15 at 06:58
  • There is a checkbox for that, when asking a question. I just wanted to share my learnings with the community ;-) – david.schreiber Apr 27 '15 at 06:59
  • Thanks for the info, haven't seen that blog post before. But I guess your question is not a problem per se, and this would have more suited as a blog post. – Rajesh Apr 27 '15 at 07:08

3 Answers3

29

Boolean literals inside the BuildConfig class are going to produce IDE warnings when using them in your code (at least within Android Studio). For example when using it in a boolean expression Android Studio will (mistakenly) recommend to simplify the boolean expression because the constant value is always the same (for current build variant that is).

Android Studio producing code warning because of missing build configuration knowledge

This warning is only because Android Studio does not know that the final value inside BuildConfig.SOME_SETTING may be different for other build variants.

To keep the code clean and free of warnings you can tell Android Studio to ignore this specific warning by adding an IDE comment like this:

Add code comments to ignore IDE warnings

But again this will add some noise to the code and reduce readability. By using the Boolean.parseBoolean(String) method to initialize your constant field, you actually trick Android Studio which will no longer be able to completely analyze your boolean expressions, thus not generating warnings any longer.

Use parseBoolean(String) to prevent IDE warnings

This approach is very useful, as it keeps your code clean and readable, without turning off important code analysis and generation of warnings.

Security & performance considerations

As mentioned by Jiří Křivánek, the usage of parsed booleans does not only "trick" the static analysis performed by IDEs, but also by compilers, code minifiers, and obfuscators - making it harder for them to remove dead code from your application. This might leave code parts inside your application binaries, that would be stripped otherwise.

david.schreiber
  • 3,851
  • 2
  • 28
  • 46
  • 2
    Maybe I'm missing something but what, exactly, does one add to build.gradle to declare a BuildConfig value using parseBoolean? – Tunga Jan 12 '16 at 14:14
  • 7
    @Tunga try following `buildConfigField 'boolean', 'SOME_FLAG', 'Boolean.parseBoolean("false")'` inside your `defaultConfig` or any flavor or build type config. – david.schreiber Jan 13 '16 at 10:13
  • Ah, I was probably missing the outer quotes, thanks. I ended up solving my issue using manifest substitutions instead. – Tunga Jan 14 '16 at 15:52
  • Doesn't it turn off compile-time optimizations though? – ratijas Feb 01 '20 at 10:37
  • Yes, they do not consider that this "very useful trick" is actually very dangerous, as I can see daily that programmers are misusing it, because they have NO clue about the !!!SIDE EFFECTS!!! of this trickery... Of course for most of the world who do not care about security, it may look like usefull... – Jiří Křivánek Nov 29 '22 at 16:17
  • Thanks @JiříKřivánek for your input. I'm curious what security considerations in particular you're talking about, and I'm certain that others, too, would be interested in you sharing your thoughts here. – david.schreiber Nov 30 '22 at 19:40
  • Please excuse the comment, I didn't see your answer before replying here. – david.schreiber Nov 30 '22 at 19:49
  • 1
    The problem is that programmers around me tend to use the BuildConfig.DEBUG for a conditional compilation - just to remove various debug utilities (and logging, ...) at all from the code. But thanks to this nasty trickery which Google did and which most of the people around me have no idea about, it actually does not work as conditional compiling. And when we have the penetration testing, the pen-test team reports back to us, like "your code contains sensitive information useful for reverse attacks". And programmers say: Impossible, we carefully reviewed it is conditionally compiled :) – Jiří Křivánek Dec 16 '22 at 10:53
3

To me, it appears that the "trick" is actually very dangerous, as you cannot do the conditional compiling based on BuildConfig.DEBUG!

if(!BuildConfig.DEBUG) { Log.d("Here we are verifying the signature!"); }

According to my reverse engineering, the logging WILL REMAIN IN THE OUTPUT .class FILE!

Which would be a very good clue for the attacker...

  • That's a very valid downside of the mentioned workaround dead branch shaking is not working well with most minifiers/obfuscators. Then on the other hand, I do not think that most developers will write if(constant) { Log.d("sensitive content"); } over and over again. Logging of sensitive data is generally a bad idea. Also, while I agree that attackers shouldn't be given an easy time deconstructing an app, the app's securit shouldn't be compromised even if they manage to read your code. – david.schreiber Nov 30 '22 at 19:48
  • I updated my answer with a section on security and performance considerations. Thank you so much for your input! – david.schreiber Nov 30 '22 at 19:53
  • You are right, my job is a kind of special, I agree that most of the world is not so picky with the code security. – Jiří Křivánek Dec 16 '22 at 10:57
0

To expand on this, what is you want to pass a boolean as a variable with gradlew to BuildConfig?

  1. add your variable to gradle.properties with a default value

     MY_VAR=false
    
  2. in your build.gradle

    android {
        defaultConfig {
            buildConfigField "boolean", "MY_VAR", "Boolean.parseBoolean(\"" + MY_VAR + "\")" 
        }
    }
    
  3. add the parameter to your gradlew command

     gradlew <task> -P MY_VAR=true
    

All this will generate the following in your BuildConfig

public static final boolean MY_VAR = Boolean.parseBoolean("true");

And obviously it will default to false if you don't pass the paramter with gradlew

S0und
  • 257
  • 4
  • 12