I am trying to swap some resources in the res/raw
folder and the jniLibs/armeabi
folder based on whether its a release buildType
or a debug buildType
. I currently have two product flavors as well.
The build.gradle file:
apply plugin: 'com.android.application'
android {
dexOptions {
preDexLibraries = false
}
compileSdkVersion 21
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.example.test"
minSdkVersion 17
targetSdkVersion 22
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
productFlavors{
phone{
applicationId "com.example.testPhone"
}
tablet{
applicationId "com.example.testTablet"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
sourceSets{
release{
res.srcDirs = ['androidRelease/res/raw']
}
}
}
dependencies {
compile project(':facebook')
}
Is using sourceSet
the right way to do so? If it is, what folder should be created so that it swaps the appropriate resources based on the buildType
only and irrespective of the productFlavors
?
EDIT: Is it even possible to swap jniLibs
and raw
folder resources?
Folder Structure:
src/main/jniLibs/armeabi
phoneRelease/jniLibs/armeabi
tabletRelease/jniLibs/armeabi
Is the folder structure correct.?
EDIT 2: Based on Xavier's answer should the gradle look like this:
android {
sourcesets {
phone {
jniLibs.srcDirs = ['phoneRelease/jniLibs/']
res.srcDirs = ['androidRelease/res/raw']
}
tablet {
jniLibs.srcDirs = ['tabletRelease/jniLibs/']
res.srcDirs = ['androidRelease/res/raw']
}
}
}
I keep reading lot of conflicting answers, some of them mention that you just need separate folders based on build variant and some mention about having to use sourceSet
?
Thanks!
However, you can create new source sets to control exactly what files Gradle compiles and packages for specific build types, product flavors (and combinations of product flavors when using flavor dimensions ), and build variants.
Build variants are the result of Gradle using a specific set of rules to combine settings, code, and resources configured in your build types and product flavors. Although you do not configure build variants directly, you do configure the build types and product flavors that form them.
To do this, the Android plugin for Gradle allows you to create multiple groups of product flavors as flavor dimensions. When building your app, Gradle combines a product flavor configuration from each flavor dimension you define, along with a build type configuration, to create the final build variant.
Till Gradle introduced ProductFlavours we were only able to build application with the a single configuration or default configuration. Since the introduction of ProductFlavours, we are able to create variables based on build types.
some of them mention that you just need separate folders based on build variant and some mention about having to use sourceSet?
Gradle/Gradle for Android has an expected structure for a sourceset:
res/
java/
jniLibs/
assets/
Where the sourceSets
closure comes into play is if, for a given sourceset, you want a different structure:
foo/
bar/
ickyNativeStuff/
assetsBecauseThatSeemsLikeADecentName/
Each build type, product flavor, and build variant can have a separate sourceset (as can androidTest
for instrumentation testing), to go along with main
. They are named the same as the build type/product flavor/build variant. These will be in the stock structure, unless you use sourceSets
to change things.
So, to roll all the way back to:
I am trying to swap some resources in the res/raw folder and the jniLibs/armeabi folder based on whether its a release buildType or a debug buildType
In the case of resources, other sourcesets overlay main
. So, if you have src/main/res/...
and src/main/debug/...
and src/main/release/...
, and you are doing a debug
build, whatever is in src/main/release/...
is ignored (as we aren't doing release
) and whatever is in src/main/res/...
and src/main/debug/...
will be used. If there is the same resource in both (src/main/res/raw/boom.ogg
and src/debug/res/raw/boom.ogg
), the debug
one trumps the main
one.
I have not experimented with varying jniLibs/
by build variant. My guess is that it will behave more like Java code, where you cannot have conflicts between what is in a build variant's sourceset and what is in main
, but that's just a guess. So, you can have the debug version of your compiled JNI code in src/debug/jniLibs/
and the release version of your compiled JNI code in src/release/jniLibs/
. Only have in src/main/jniLibs/
any libraries that are not varying. That being said, as I mentioned, I haven't tried this, and so there may be hiccups here.
So, I would expect you to not have a sourcesets
closure in build.gradle
, and to just use the stock sourcesets structure, for your various bits:
src/
main/
...
debug/
jniLibs/
res/
raw/
release
jniLibs/
res/
raw/
Anything that's normally under src/main/
can be put in a different folder:
src/<element>/AndroidManifest.xml
src/<element>/java
src/<element>/res
src/<element>/assets
src/<element>/resources
src/<element>/jni
src/<element>/jniLibs
src/<element>/aidl
src/<element>/rs
Where element
is the name of a build type
or a product flavor
. If your variant includes such a element (build type or flavor), then that source set is also used in addition to src/main
Note that the location is really not relevant if you have configured it.
What matters is that there is a android.sourcesets.main
element that contains the sources common to all variants, and each variant has a set of sourcesets.
For instance if you have a flavor phoneRelease
it's really using the following sourcesets:
android.sourcesets.main
android.sourcesets.phone
android.sourcesets.release
android.sourcesets.phoneRelease
If you have another variant tabletRelease
, it'll use the following:
android.sourcesets.main
android.sourcesets.tablet
android.sourcesets.release
android.sourcesets.phoneRelease
So the phone
/tablet
sourceset is different and is where you'd put the variant specific sources, unless you want to be even more specific and use the phoneRelease
/tabletRelease
sourcesets (though those are less used generally.) By default these would be src/phone/...
and src/tablet/...
(or src/phoneRelease/...
) but you can change that however you want and as long as it's connected to the android.sourcesets.*
objects it'll be fine.
for example, doing:
android {
sourcesets {
phone {
jniLibs.srcDirs = ['phoneRelease/jniLibs/']
}
tablet {
jniLibs.srcDirs = ['tabletRelease/jniLibs/']
}
}
}
is fine. But do be aware that you only changed the jniLibs folder and not the other source elements (java, res, etc...)
If you kept the default location for the main
sourcesets, I'd just keep everything under src/
You can see more info about sourcesets and how multiple sourcesets are combined here: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Sourcesets-and-Dependencies
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With