Gradle swap jniLibs resources based on build flavor - android

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!

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:
Android resources in res/
Java source tree in java/
Pre-compiled JNI libraries in jniLibs/
Assets in assets/
Etc.
Where the sourceSets closure comes into play is if, for a given sourceset, you want a different structure:
Android resources in foo/
Java source tree in bar/
Pre-compiled JNI libraries in ickyNativeStuff/
Assets in assetsBecauseThatSeemsLikeADecentName/
Etc.
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

To use flavors to vary source sets,
productFlavors{
phone{
}
tablet{
}
}
Now structure your code like,
src
main
phone
tablet
The code in main is common between both flavors, but the code in phone or tablet is only included when the respective flavor is built. That's it, you don't need to do anything else.
The structure under phone and tablet is the same as under main (res, java, etc). You can also have a custom AndroidManifest.xml under the flavor directory. Gradle attempts to merge the flavor's AndroidManifest.xml with the one in main. In some cases you have to provide rules for how to merge.

Related

Android gradle pulling files to assets

Android: I have some files shared by other projects, and like them packaged under assets/.
/android/app/src/main/assets/a.xml
/projects/shared/b.xml
how to put both a.xml and b.xml under assets/ in apk?
You can add arbitrary directories to the locations that Gradle (and the Android Plugin for Gradle) looks for assets.
For example, when testing migrations in Room, we use this to get our Room-generated historical schemas added to our instrumentation test's assets:
sourceSets {
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
}
Here, we are saying that we want to add a new directory to the set of directories that populate the assets for the androidTest source set.
Similarly, you could do something like:
sourceSets {
main.assets.srcDirs += ...
}
where you would have to figure out the appropriate ... to point Gradle to wherever your other files are.
Note that the sourceSets closure goes inside the android closure of your module's build.gradle file.

Product Flavor structure

I have a project that uses ~30 product flavors. Apart from the "main" code, the flavors don't have much to them, just some unique resources. Since there are so many, I would like to structure my code directories like this to make it more organized:
src
main
java
res
productFlavors
flavor1
java
res
But the build doesn't recognize the flavors when they are on a different level than the "main" folder. Is there any way I can make this work?
I have a project that uses ~30 product flavors
One more, and you'll match Baskin-Robbins' original ~31 flavors.
But the build doesn't recognize the flavors when they are on a different level than the "main" folder. Is there any way I can make this work?
You can override where source comes from in your module's build.gradle file. While I haven't tried it for your scenario (only for building Eclipse-style projects using Gradle), something like this should work:
android {
// lots of cool stuff here
sourceSets {
flavor1 {
manifest.srcFile 'src/productFlavors/flavor1/AndroidManifest.xml'
java.srcDirs = ['src/productFlavors/flavor1/java']
aidl.srcDirs = ['src/productFlavors/flavor1/aidl']
res.srcDirs = ['src/productFlavors/flavor1/res']
assets.srcDirs = ['src/productFlavors/flavor1/assets']
}
// lather, rinse, repeat
}
}
If you stick to the fixed pattern of src/productFlavors/.../ (where ... is the flavor name), you can probably use a bit of Groovy scripting to iterate over an array of flavor names and wire up the sourcesets accordingly.

android gradle flavors in the last Android studio

I would like to create two falvors for my project. I did this successfully in the past but with new ANdroidStudio I a little bit concerned how to do that. The official guide is out-dated.
In the past what we need to do is to create additional folders on the level of "src" folder. In the current version of AndroidStudio we have app->{/java;/manifests;/res} structure and we can create folder only under the same package and I don't see the way to create additional folder for "res"
Can you advise please how I can create flavors for my app?
The official guide is out-dated.
The core of the official guide's section on product flavors seems fine to me.
In the past what we need to do is to create additional folders on the level of "src" folder.
That would define a sourceset for a product flavor. You still need to declare the product flavor in build.gradle for the module, via a productFlavors closure or via the Project Structure dialog.
In the current version of AndroidStudio we have app->{/java;/manifests;/res} structure
Switch from the Android view of your project contents to the Project view, via the drop-down just above the project structure tree.
You will start with a tree like:
and change it to a tree like:
Can you advise please how I can create flavors for my app?
Add a productFlavors closure to your module's build.gradle file, manually or via the Project Structure dialog:
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.commonsware.myapplication"
minSdkVersion 8
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
vanilla {
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
}
If you want to have alternative source for that product flavor (Java, resources, manifest, etc.), create src/.../ in the project, where ... is the name of your flavor (src/vanilla/ would correspond with the sample build.gradle shown above). To create this directory, either:
in the Project view, create it as you would any other directory
in the Android view, just start defining a resource, and the dialog that appears will have a drop-down for the sourceset:
However, as I do not know how to put Java code in a particular sourceset this way, I always work in the Project view.
Maybe try with build types, somewhat similar to this post. You may change resource folders in that fashion

Android Studio Gradle Build Flavors

I am having troubles understanding Build Flavors in Android Studio. I am trying to achieve a simple thing: buidling 2 signed APK's with a minor code change. The "pro" APK just has a different drawer.xml in res/layout/. I've read a few things in the Documentation and here on StackOverflow but I don't see anything happen with my build.gradle changes.
my current build.gradle file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.4.+'
}
}
apply plugin: 'android'
dependencies {
compile files('libs/android-support-v4.jar')
compile files('libs/GoogleAdMobAdsSdk-6.4.1.jar')
}
android {
compileSdkVersion 17
buildToolsVersion "17.0.0"
defaultConfig {
minSdkVersion 14
targetSdkVersion 17
}
productFlavors {
lite {
packageName = 'com.mikebdev.refuel'
}
pro {
packageName = 'com.mikebdev.refuelpro'
}
}
sourceSets{
android.sourceSets.pro {
res.srcDirs = ['src/main/res_pro']
}
}
}
I created a new folder:
/src/main/res_pro/layout/drawer.xml
What am I doing wrong here?
EDIT
I updated my build.gradle file above.
After resetting my whole Android Studio because of some other instabilities I am now able to choose in the bottom left corner my build variants (lite-debug, lite-release, pro-debug, pro-release) Why even those debug AND release variants?
This seems to work now as it should.
I added a answer below
After resetting my whole Android Studio because of some other instabilities I am now able to choose in the bottom left corner my build variants (lite-debug, lite-release, pro-debug, pro-release) Why even those debug AND release variants?
I created a whole new Project with Module and copy&pasted everything from my old project which I exported from eclipse a while back in there.
NOW it works.
My Android-Studio was kinda broken before my reinstall. More crashes than there should be, some strange behaviors ans such stuff.
What you're doing wrong is that you are putting your file in /src/main/res_pro/layout/drawer.xml and not setting it in the gradle. the default location for the flavor that you created would be:
/src/pro/res/layout/drawer.xml
With this build script you are using build types AND flavors. For changing the xml file you only need the flavors. Try to delete buildTypes and use the productFlavor block as child of android.
The changing of the res folder of the pro flavor should go into the sourceSets Block right after all the changes of the main sourceSet

Custom old Android project structure in Gradle

We have a project structure of the form
srcsrc_flavor1src_flavor2resres_flavor1res_flavor2
The core logic and resources are placed in src and res folder resp. The flavoured folders only contains few files which separate the two flavors.
Im trying to define this project structure withing the build.gradle file but havnt found any success. Also Im trying to use the prductFlavor tags to create simultaneous builds of the two flavors but no success. Doing all this within the Android Studio latest build
Assuming you have define your flavors like this:
productFlavors {
flavor1 {
...
}
flavor2 {
...
}
}
You can modify the sourceSets of each flavor
android.sourceSets.flavor1 {
java.srcDirs = ['src_flavor1']
resources.srcDir = ['res_flavor1']
}
android.sourceSets.flavor2 {
java.srcDirs = ['src_flavor2']
resources.srcDir = ['res_flavor2']
}
I hope this help... (don't hesitate to add more details about your problems since it will help us to help you)
Last remark: according my experience, Android-Studio is not very stable yet and not full-featured yet regarding gradle<-->IDE sync. So I strongly suggest you to always test your gradle scripts from the command line.

Categories

Resources