Android Tutorial Conditional Compilation & Build Configurations

B4A v3.80 adds support for conditional compilation.

From Wikipedia:
In computer programming, conditional compilation is compilation implementing methods which allow the compiler to produce differences in the executable produced controlled by parameters that are provided during compilation.

Conditional compilation allows you to exclude parts of the code based on the selected build configuration. You can use it to create several applications from the same project. For example you can create one application with ads and another application without ads.

Build Configurations

The build configurations dialog is available under Project -> Build Configurations (Ctrl + B).

SS-2014-05-08_09.58.38.png


This dialog allows you to edit or add new configurations and to choose the current active configuration.
A build configuration is made of a package name and a set of conditional symbols.
The package name replaces the previously global package field. This means that you can produce APKs with different package names from the same project. Note that multiple configurations can share the same package name.

The conditional symbols define the active compiler symbols. This allows you to exclude parts of the code based on the chosen build configuration.
You can set multiple symbols separated with commas.

There are several built-in symbols:
- B4A: B4A, DEBUG and RELEASE. Either DEBUG or RELEASE will be active based on the deployment mode.
- B4J: B4J, DEBUG, RELEASE, UI or NON_UI (based on the app type)
- B4i: B4I, DEBUG, RELEASE

Code Exclusion

With the conditional compilation feature you can exclude any code you like from the code editor, manifest editor and designer script (any text can be excluded, including complete subs and attributes).
Excluded code will not be parsed and will be effectively removed before it reaches the compiler.
Note that the manifest editor and designer script will not visualize the excluded code. However it still works properly.

The code exclusion syntax:

SS-2014-05-08_10.19.51.png


B4X:
#If [symbol]
...
#End If

Each build configuration holds a set of symbols. Multiple configurations can share all or some of the symbols. This makes it possible to include or exclude code in several different configurations.

Starting from B4A v5, B4J v3 and B4i v2 more complex expressions are supported.
For example:
B4X:
#If FULL and Not(WITH_ADS)
'Do something
#Else If WITH_ADS OR (TRIAL And IN_APP)
'...
#Else
'...
#End If
 
Last edited:

Humberto

Active Member
Licensed User
Thanks "canalrun" for the express answer.

For the icon I use the manifest solution
B4X:
#if paid
    SetApplicationAttribute(android:icon, "@drawable/iconp")
#end if   
#if free
    SetApplicationAttribute(android:icon, "@drawable/icon")
#end if

But for the APK name maybe I´ll use a BAT because it must be run after the compilation.
 

Computersmith64

Well-Known Member
Licensed User
Can I change the apk name for Free and Paid compilation ?
You can change the apk name based on the build configuration - in fact that's what I do with one of my apps. In hindsight though, it probably would have been better to have a single release of the app - ie: a free version with an in-app purchase. That's what I did when I ported it to iOS & it makes maintaining releases much easier.

- Colin.
 

Derek Johnson

Active Member
Licensed User
I would like to be able to specify whether a particular library was conditionally included or not. (specifically Google Fused Location Provider). I would like to have the option of generating code that uses the GPS device directly or uses the Google Fused Location Provider. The point is that this is a really big library and significantly increases the App size and compilation time. I've found no discussion about how to do this.

I suspect that there is a way, is there a solution for this?

Derek
 

Derek Johnson

Active Member
Licensed User
Libraries added with #AdditionalJar can be added / removed with conditional compilation.

So I remove the explicit library selection and use #AdditionalJar to (conditionally) get it back.

I knew there must be a way! As a lot of other people have said, this product is brilliant and the support is second to none.

Right: Just hit a snag with this code:

B4X:
B4A version 4.30
Parsing code.                           Error
Error parsing program.
Error description: Unknown type: fusedlocationprovider
Are you missing a library reference?
Occurred on line: 25
Private FLP1 As FusedLocationProvider

This is the start of the code:

B4X:
#Region  Project Attributes
    #ApplicationLabel: Nearest Library
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False

#If FLP
    #AdditionalJar: FusedLocationProvider.jar
#End If

#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

#If FLP
    Private FLP1 As FusedLocationProvider
#End If

I tried a couple of things to see if I had got the syntax wrong:

#AdditionalJar: FusedLocationProvider.jar

#AdditionalJar: FusedLocationProvider (no qualifier)

#AdditionalJar: fusedlocationprovider.jar (lower case - plus renaming library jar)

Thanks

Derek
 
Last edited:

sorex

Expert
Licensed User

Computersmith64

Well-Known Member
Licensed User
When I look at the configs here > https://www.b4x.com/android/forum/t...build-configurations.40746/page-2#post-246478

I was wondering if you didn't need to enter a different package name for each version?

or does that get combined to the package name during compile?

like...

build names : Full & NoAds
package name: com.test

becomes com.test.full & com.test.noads in the final packages?

I don't think that's the case. The package name will be whatever you put in the Package Name field - so in your example, you'd get 2 packages names "com.test". Actually, you'd get one, because it would get overwritten on each build.

Also, per my comment here, I'd advise against having separate packages for different build variations of an app - it becomes very time consuming to have to update multiple app listings on Google Play. Much easier to just have one app & use In-App Billing to differentiate them.

- Colin.
 

sorex

Expert
Licensed User
You're right but in-apps requires more setup and code compared to a seperate app where you just define the payment on google play.

Also, how does in-app work when people don't use google play but for instance only Amazon ?
 

Computersmith64

Well-Known Member
Licensed User
You're right but in-apps requires more setup and code compared to a seperate app where you just define the payment on google play.

Also, how does in-app work when people don't use google play but for instance only Amazon ?

Amazon have their own payment API, but unless there's a B4A wrapper for it (or you're a gun wrapper developer yourself) I guess you can't use it. My strategy to-date has to only offer my free apps on Amazon.

- Colin.
 

sorex

Expert
Licensed User
ok, makes sense. but I guess in most cases people would have a google play account aswell.
 
Top