Reputation: 6620
my situation is this: i have a project, which uses some generated code. In the generated code, a certain URI is hardcoded in pretty much all files.
So, at some point i got to two generated codebases: one targeting DEVELOPMENT, another targeting STAGING.
I want to solve that via Gradle just as I would via Makefiles.
So, at first i made a new Module in the root of my project named SOAP-DEV and SOAP-STAGE, defined two new variables in gradle.properties called
# Make sure only one of these is set to 'true' and *do* set the other one to 'false'. Please.
USE_STAGING_SOAP=
USE_DEVELOPMENT_SOAP=1
I ended up using 1 and blank, because true
and false
didn't seem to do the trick and both counted as true.
So, once the building issue was done with and only one of them seemed to be building (both actually, but I was getting only one using <dev/stage> soap pack
line, i think that was actually ok and that the proper one was being built.
then I hit another roadblock - it seems my project's main module - app
can't see files outside it's folder, which makes sense.
Now I'm trying with a different approach - to have SOAP-STAGE and SOAP-DEV be subfolders of ProjectName/app
instead of ProjectName
so the #import line can actually see the sources it needs to see to build properly.
Yet, that's not happening :/
What is the proper way of setting a configurable choice of which folder to build for only a part of the project's codebase, but so that they are seen by the project's #import in the classes?
I would gladly revert to the old idea of having both SOAP folders as modules in my project, if I could get the classes inside the project to see the related-module's classes, namely the soap classes.
To better illustrate what I'm trying to do, here's my main module's gradle.build file. I hope you'll understand what I'm trying to do with this.
import java.text.SimpleDateFormat
apply plugin: 'com.android.application'
android {
signingConfigs {
hockeyApp {
keyAlias 'myKeyAlias'
keyPassword 'myKeyAliasHA'
storeFile file('../myKeystore.jks')
storePassword 'myKeyAliasHA'
}
}
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.my.application"
minSdkVersion 15
targetSdkVersion 21
versionCode 1
versionName getVersion()
}
buildTypes {
hockeyApp {
signingConfig signingConfigs.hockeyApp
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
android.enforceUniquePackageName=false
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.0.0'
compile 'com.facebook.android:facebook-android-sdk:4.0.0'
compile 'com.google.android.gms:play-services:7.0.0'
compile 'com.android.support:recyclerview-v7:21.0.0'
compile 'com.daimajia.swipelayout:library:1.1.9@aar'
compile files('libs/dpdsoaplib.jar')
compile project (':androidNeoReaderSDK')
if(USE_STAGING_SOAP == 1)
{
compile {
source = 'SOAP-STAGE/src/main/java'
}
}
if(USE_DEVELOPMENT_SOAP == 1)
{
compile {
source = 'SOAP-DEV/src/main/java'
}
}
compile "com.android.support:support-v4:21.0.+"
compile 'com.google.maps.android:android-maps-utils:0.3+'
}
def getVersion() {
def Calendar cal = Calendar.getInstance();
def SimpleDateFormat dateFormat = new SimpleDateFormat("MMddHHmmss");
def StringBuilder sb = new StringBuilder("v");
sb.append("0.2");
sb.append(".");
sb.append(dateFormat.format(cal.getTimeInMillis()));
sb.append("a");
return sb.toString();
}
However, if I can actually get both of these folders (SOAP-DEV and SOAP-STAGE) to be added as source folders to the project/module, I think that would resolve the problem of not being able to import proper classes, which was only caused by the classes being moved from the ProjectName/app/src/java folder, to the ProjectName/SOAP-DEV/src/java and ProjectName/SOAP-STAGE/src/java folders.
The two folders do have identical packagenames and contain classes of the same name which only point to a different soap server.
So, people, any ideas? I thought this Gradle was supposed to introduce some build system / makefile functionalities to android studio, but so far it does not seem to be the case.
Right now i'm trying something in between - to have both folders as Modules in the root of the project but also have one or the other's code visible in my app
module's import statements.
Upvotes: 3
Views: 2473
Reputation: 6620
So, the answer (in the end) came down to this:
The structure was altered a bit, and two new subfolders were added at the "main module" (main module = app) level.
ProjectRoot/app/src/main/my/package/name/...
ProjectRoot/app/src/soap_dev/my/package/name/...
ProjectRoot/app/src/soap_stage/my/package/name/...
Then, the generated code got moved from
ProjectRoot/app/src/main/my/package/name/backend/soap/generated
to
ProjectRoot/app/src/SOAP_DEV_/my/package/name/backend/soap/generated
ProjectRoot/app/src/SOAP_STAGE_/my/package/name/backend/soap/generated
Two new build flavors were made in the module "app"
productFlavors {
SOAP_DEV_ {
}
SOAP_STAGE_ {
}
}
And that resulted in the flavors applying to all current build configurations available to the project.
Upvotes: 0
Reputation: 28706
Your initial idea of having 2 modules in your root directory with both version of your generated code is a good start. Now, using a variable to dynamically changing the content of your app is not supported by gradle.
The philosophy behind this limitation is that it MUST be possible to evaluate the need of executing a gradle task simply by looking at it's inputs and outputs. (i.e. input didn't change ==> no need to re-execute the task).
Fortunately, gradle offers alternative ways of writing flexible builds:
You can use flavors (i.e. variations of the same product).
Define 2 flavors :
android {
...
productFlavors {
dev{}
staging{}
}
}
dependencies {
devCompile project(':SOAP-DEV')
stagingCompile project(':SOAP-STAGE')
...
}
Note that the prefix in dependencies is exactly the name of the flavors.
This will produce 2 apks : MyApp-dev.apk and MyApp-staging.apk
Upvotes: 1