I am facing an issue where I am not able to generate the desired resource files. In my project setup I have defined certain values in resource files(keys.xml) that are different between flavors(amazon, googlePlay). The problem mainly occurs because the keys are also different between the live/qa builds.
So the final keys I would like to have are:
amazonPaidQa -> keys from 'src/amazon/res/values/keys.xml'
amazonPaidLive -> keys from 'src/amazonPaid/res/values/keys.xml' (not working as this requires me to define the keys file in 'src/amazonPaidLive')
My question is if it is possible to define resources in 'interim' build variants like the above mentioned 'amazonPaid' so that I would not have to duplicate that file between all possible live build variants(amazonPaidLive, amazonFreeLive). Or maybe someone has a better suggestion how to approach this problem?
build.gradle definitions
buildTypes {
qa {
//config
}
live {
//config
}
}
flavorGroups "market", "client"
productFlavors {
//define the market flavors
amazon {
flavorGroup "market"
}
googlePlay {
flavorGroup "market"
}
//define the client flavors
free {
flavorGroup "client"
packageName "com.example.free"
}
paid {
flavorGroup "client"
packageName "com.example.paid"
}
}
The folder structure is the following:
- src/main
-- AndroidManifest.xml
-- res/values/keys.xml
- src/live
- src/qa
- src/amazon
-- res/values/keys.xml
- src/googlePlay
-- res/values/keys.xml
- src/paid
- src/free
Android Manifest snippet
<application>
...
<meta-data android:name="app_id" value="#string/app_id" />
</application>
Related
I have configured my project to have multiple product flavors. I have the following code in my module build.gradle:
android {
// Rest of the configuration omitted for clarity
buildTypes {
debug {
// ...
}
release {
// ...
}
}
productFlavors {
paid
free
}
}
If I create a file (any file: Java, resources, ...), in the paid, free, debug or release, it is recognized by Android Studio and I can use it in my project.
However, if the same file is created in paidDebug (or a similar folder) it is not recognized in Android Studio. Do I need any extra configuration for this to work? Is this not supported (yet)?
Source code files with the same name should be placed in all of the alternative source sets (but not in the 'main').
Either:
app/src/free/java/com/domain/myapp/MainActivity.java
app/src/paid/java/com/domain/myapp/MainActivity.java
Or:
app/src/freeDebug/java/com/domain/myapp/MainActivity.java
app/src/freeRelease/java/com/domain/myapp/MainActivity.java
app/src/paidDebug/java/com/domain/myapp/MainActivity.java
app/src/paidRelease/java/com/domain/myapp/MainActivity.java
Resource files with the same name can be placed in any source set, including 'main'.
app/src/main/res/layout/activity_main.xml
app/src/paidDebug/res/layout/activity_main.xml
app/src/paidRelease/res/layout/activity_main.xml
In this case, when building the 'free' flavor, the layout file from 'main' set will be used. But, during the build of the 'paid' flavor, the specific version of the layout will be used.
You can specify specific source directories in your build.gradle file. For example, to add testFreeRelease to unit test sources and testFree to android integration test sources:
android {
[...]
sourceSets {
main.java.srcDirs += 'src/main/java'
testFreeRelease.java.srcDirs += 'src/testFreeRelease/java'
androidTestFree.java.srcDirs += 'src/androidTestFree/java'
}
}
This also works for Kotlin. Just switch java with kotlin.
I'm looking for how can I create build types directory for flavors.
Right now I have 2 flavors called dev and prod and I want to create debug and release directories in app/src folder.
My app/src folder looks like this:
main
androidTest
test
release
debug
About what I'm trying to achive:
I'm trying to add a sufix to my package in debug mode. So I achived that in build types block. in addition I have set minSdkVersion 21 in one of my flavors so that android gradle builds faster.
You can create directory that are the combination between build types and flavors naming them with this convention: buildtypeFlavor
For what you want to achieve you have to insert in your build.gradle file both build types configurations and flavors configurations.
android {
buildTypes {
debug {
applicationIdSuffix '.debug'
}
release {
}
}
productFlavors {
dev {
minSdkVersion 21
}
prod {
}
}
}
Now you can create dirs under src to have the combination of both, in this case: devDebug, devRelease, prodDebug, prodRelease
root
|___module
|___src
|__devDebug
|__devRelease
|__prodDebug
|__prodRelease
I am using Android Studio and Gradle to build Android applications. I would like to have different strings within the Java code based on which type of build it is (debug vs. release). What is the best way to do this?
For example - I want to have different URLs if I am in debug or release. Also, I want to specify different GUIDs and other keys / strings.
The obvious hacky way to do this is to do a search and replace of a string in AndroidManifest.xml or worse yet, in a Java file. This approach seems error prone and hacky to me - is there a better way to do this?
There are many ways you can do this, although I usually do
android {
buildTypes {
release {
buildConfigField("String", "URL", "your_url_on_release")
}
debug {
buildConfigField("String", "URL", "your_url_on_debug")
}
}
}
You then can access them on your java code by using:
BuildConfig.URL
You can test this using Android Studio Build Variants, by changing your application variant to debug or release ( e.g. http://prntscr.com/8waxkw)
You have many solutions to do this, here's a simple case:
buildTypes {
debug { ... }
release { ... }
}
productFlavors {
staging { ... }
production { ... }
}
build types are for build management proguarding, debugging, signing, etc.
productFlavors are for all app internal configuration.
If you want to add resources related to the flavours you can create and add to src/(flavor_name)/res/values/ folder your urls.xml config file.
With this, in android studio, you'll directly see, all the builds variants in the corresponding window and the right urls.xml file associated to the current context and leave the gradle config clean.
Of course, this method works also for any resource you would need in your app.
For more detail, you can read this : http://developer.android.com/tools/building/configuring-gradle.html#workBuildVariants
I would do it with product flavors as explained in this post.
I have an issue with test and androidTest source directories for multi-dimension flavors.
Given the following flavors:
flavorDimensions "taste", "serving"
productFlavors {
chocolate {
flavorDimension "taste"
}
strawberry {
flavorDimension "taste"
}
kiwi {
flavorDimension "taste"
}
sample {
flavorDimension "serving"
}
whole {
flavorDimension "serving"
}
}
There are no issues with "non-test" source directories (of any flavor combination) being recognized in Android Studio:
src/sample, src/whole, src/chocolate, src/strawberry, src/kiwi,
src/chocolateSample, src/chocolateWhole, src/strawberrySample, src/strawberryWhole, src/kiwiSample, src/kiwiWhole
My issue is with "test" source directories.
Only single dimension flavors are recognized: src/testSample, src/testWhole, src/testChocolate, src/testStrawberry, src/testKiwi.
Multi-Dimension flavors are not: src/testChocolateSample, src/testChocolateWhole, src/testStrawberrySample, src/testStrawberryWhole, src/testKiwiSample, src/testKiwiWhole
This is also the case for the "androidTest" equivalent source directories.
I am under the impression that it is the app.iml which is not correctly generated. While understanding that we should NEVER do this, the folders are correctly recognized if I were to manually add in the missing entries.
Why should this work with non-test source directories but fail with test source directories? Is this a known issue or a limitation by the gradle plugin?
I tried researching this, but only found topics related single flavor dimensions for test source folders or mult-dimension flavors for non-test source folders. There is nothing with regards to multi-dimension flavors for test source folders.
You should be able to fix this by modifying your android app build.gradle file. For example, to add testChocolateSample to unit tests and testChocolate to android integration tests:
android {
[...]
sourceSets {
main.java.srcDirs += 'src/main/java'
testChocolateSample.java.srcDirs += 'src/testChocolateSample/java'
androidTestChocolate.java.srcDirs += 'src/androidTestChocolate/java'
}
}
This also works for Kotlin. Just switch java with kotlin.
I am wondering if it is possible to supply files or configuration settings for a specific flavor group combination. For example, I have 2 flavor groups, with 2 different flavors each:
Flavor Group: Version
v2
v3
Flavor Group: Type
free
full
When ordered "Type", "Version" I am able to build 4 different flavors of my app:
FreeV2
FreeV3
FullV2
FullV3
And my source tree looks like this:
/src
/free
/res
/full
/res
/v2
/java
/res
AndroidManifest.xml (features and permissions for v2 flavors)
/v3
/java
/res
AndroidManifest.xml (features and permissions for v3 flavors)
This is exactly what I want, and works very well for my project. However, I wish I could provide files for a specific flavor group combination. For example, I want to provide different AndroidManifests for FullV3 and FullV2. I don't think this is possible, or? For example:
/src
/free
/res
/full
/res
/v2
/java
/res
AndroidManifest.xml (features and permissions for v2 flavors)
/v3
/java
/res
AndroidManifest.xml (features and permissions for v3 flavors)
/fullv3
AndroidManifest.xml (features and permissions for full v3 only!)
/fullv2
AndroidManifest.xml (features and permissions for full v2 only!)
I would be nice to be able to do this in the gradle build file as well:
productFlavors {
free {
packageName ...
flavorGroup "type"
}
full {
packageName ...
flavorGroup "type"
}
v2 {
packageName ...
flavorGroup "version"
}
v3 {
packageName ...
flavorGroup "version"
}
fullv2 {
... <-- specifically for the full-v2 combination
}
fullv3 {
... <-- specifically for the full-v3 combination
}
}
Note: one solution would be to only have 1 flavor group and define the 4 flavors explicitly:
freeV2
freeV3
fullV2
fullV3
However, this is not a viable solution for me since I would have to duplicate all the version specific code for the free and full flavors of each version.
This functionality was added in version 0.7.0 of the Android plugin for Gradle
http://tools.android.com/tech-docs/new-build-system <--As of 1/6/14, this link is active
You can now have a variant specific source folder if you have flavors.
Only for app (not library or test). Name is src/flavorDebug/... or src/flavor1Flavor2Debug/
Note the camelcase naming, with lower case for first letter.
Its components (res, manifest, etc...) have higher priority than components from build type or flavors.
There is also a "flavor combination" source folder available when more than one flavor dimension is used. For instance src/flavor1Flavor2/
Note that this is for all combinations of all dimensions.
Its priority is higher than single-flavor sourcesets, but lower than build-types.
Update 1/30/2014
IntelliJ IDEA v13.0.2 (Build 133.696) now supports Android Gradle Plugin changes made in 0.7.0
Files will be merged when the flavors come together. So if you have a manifest in full and in v3, they will be combined when fullV3 is generated. This way you can get the combo generated.
As per the question asked you want different AndroidManifest file for Full version of both v2 and v3. So instead of going with flavors for full and free, you can use combination of flavors and buildTypes as per your convenience.
For example
I know full and free should be product flavors not build types but your requirement says that full and free are your buildTypes and v2 and v3 are your app flavors
buildTypes {
debug {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
full{
runProguard false/true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
signingConfig signingConfigs.prodSigning // write your signingConfig
}
free{
runProguard false/true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
signingConfig signingConfigs.prodSigning // write your signingConfig
}
}
productFlavors{
v2 {
//required configuration for full version
}
v3 {
//required configuration for full version
}
}
Now your project structure should look like this .
--src
---main
----java
----res
----Manifest
---full
----java
----res
----Manifest(Manifest you want for Full Version)
---free
----java
----res
----Manifest (Manifest you want for Free Version)
---v2
----java
----res
----Manifest
---v3
----java
----res
----Manifest
After Sync with Gradle this will give combinations of build types in build variant tab in left pane in AS and will create different tasks for the same.
Go to Build Variant and generate the build from drop down according to your choice.
It will give you Build Variants like this
To set configuration for each flavor combination in your build file you could use the solution I proposed here: https://stackoverflow.com/a/26585241
You can then use and variantFilter to iterate through all flavor combinations and match on the name of each combination (just like the name used when creating "flavor combination" source folders where you can place specific resources as mentioned in the answer from #abest):
android.variantFilter { variant ->
def flavorString = ""
def flavors = variant.getFlavors()
for (int i = 0; i < flavors.size(); i++) {
flavorString += flavors[i].name;
}
if(flavorString.equalsIgnoreCase("fullv2")) {
variant.getDefaultConfig().applicationId "com.example.fullv2"
}