While trying to run gradle's assemble task for specific build variants, I've noticed some weird thing. Consider next configuration:
android {
buildTypes {
release {
}
}
productFlavors {
flavorDimensions "shape", "color"
rect {
dimension "shape"
}
circle {
dimension "shape"
}
red {
dimension "color"
}
green {
dimension "color"
}
}
}
In such case build system recognizes tasks like assembleRect, assembleRectRed, assembleRectRedRelease.
But when I ask for assembleRectRelease it claims that there is no such task. IMO it is pretty clear that I want to assemble RectRedRelease and RectGreenRelease artifacts, isn't it?
Does anybody know what is the reasons of such behavior? Or maybe there are some build system limitations?
P.S. This is related at least to gradle plugin version 2.1.0.
Related
What is the best way to apply a gradle plugin to only a specific build variant. For example we might have
usStage
usDebug
usProduction
but a plugin has a lot of build overhead for developers (several minutes), and has no need to run on usStage and usProduction. Normally for libraries you would just use something like releaseImplementation, but I am not aware of anything like this existing at the gradle plugin level.
So right now we have somethig like this at the top of our app/build.gradle.kts in Android
plugins {
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
id("com.heapanalytics.android")
id("com.gladed.androidgitversion") version "0.4.14"
id("jacoco-reports")
}
where id("com.heapanalytics.android") is the culprit of slow build times on debug, where it is not even needed.
Is there a way that within our build variants, to only apply this for usProduction?
I have tried something like this:
plugins {
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
id("com.gladed.androidgitversion") version "0.4.14"
id("jacoco-reports")
}
android {
defaultConfig {
...
signingConfigs {
create(release) {
...
}
getByName(debug) {
...
}
}
buildTypes {
getByName(debug) {
...
}
getByName(release) {
...
apply(plugin = "com.heapanalytics.android")
...
}
But it just applies the plugin to every variant still, I believe because that block configures all variants even when you are only building one.
if (project.hasProperty(BuildProperties.Metrics.ENABLE_HEAP)) {
apply(plugin = "com.heapanalytics.android")
}
Tried something like this too, which may work, but was not really sure it is the best way. Feels hacky.
You can do this in many ways but for the most recent solution I know and use do:
android {
productFlavors {
flavourName{
apply plugin: 'com...'
}
}
}
For more solutions please reference to here.
Been working on an Android Webview app and I've only just now started to use a node_modules folder in there, so naturally I did some research on how to exclude it and I ended up at this question here
Tried some of the answers and the one that actually worked the best for me was the one about aaptOptions
So of course naturally I'm playing around with it, trying to figure out what works, and I succeed at excluding a few folders from the debug apk.
aaptOptions {
ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:'
}
And I can indeed confirm that those folders aren't included in the final APK in Android studio! Success!
So then I realize that I can do something a bit clever: when I'm running my app, testing it on my end, debugging it, I like to have certain credentials in certain places automatically put in - I do this with javascript - but obviously I don't want these credentials included in the APKs I might send out into the world -- even though I've already coded it to not input the credentials automatically unless I'm debugging, the credentials are still actually in the javascript files, and presumably someone could look in there and see them!
So my idea was to create a file, 'example-creds.js', and use aaptOptions to not include that file, ONLY on release builds, so I came up with something that looks approximately like this (extra details stripped out):
android {
buildTypes {
release {
aaptOptions {
ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:!example-creds.js:'
}
}
debug {
aaptOptions {
ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:'
}
}
}
}
BUT IT DOESN'T WORK! I've tested it and it seems to run whatever the last-defined aaptOptions is, regardless of the build type. If I put release after debug, I get no example-creds in either build. If I put debug after release, I get example-creds in both.
How can I get what I'm looking for?
Generally it should be possible to configure AaptOptions alike any other configuration block. Try to run that script afterEvaluate (which is after those aaptOptions had been evaluated):
task afterEvaluate {
doLast {
applicationVariants.all { variant ->
variant.outputs.all { output ->
def pattern = "!node_modules:!jsunmin:!.idea:!jade:!css-scss:"
if(variant.getBuildType().getName() == 'release') {
pattern = pattern + "!example-creds.js:"
}
aaptOptions.ignoreAssetsPattern = pattern
}
}
}
}
aaptOptions's ignoreAssetPattern cannot be set in afterEvaluate block. If you try, you will run into this error
com.android.build.gradle.internal.dsl.AgpDslLockedException: It is too late to set ignoreAssetsPattern
It has already been read to configure this project.
Consider either moving this call to be during evaluation,
or using the variant API.
The solution is to use the variant API during configuration (also note that aaptOptions is depricated and is renamed to androidResources AGP 7.1.3 onwards)
android {
buildTypes {
release {
androidResources {
ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:'
}
}
debug {
androidResources {
ignoreAssetsPattern '!node_modules:!jsunmin:!.idea:!jade:!css-scss:'
}
}
}
androidComponents {
onVariants(selector().withName("release")) { variant ->
def pattern = variant.androidResources.ignoreAssetsPattern
pattern.add("!example-creds.js")
}
}
}
I got a project configured with multiple variants and flavors:
buildTypes {
debug {
}
release {
}
}
flavorDimensions "default"
productFlavors {
mock {
}
alpha {
}
beta {
}
prod {
}
}
Whenever I open the project from another one (so starting Android Studio), it selects the mockDebug variant by default. Often I end up build this one first, then realizing I'm on the wrong variant.
Is there a way to tell Android Studio to defaults to one variant, let's say betaDebug?
Technicals: Android Studio 3.1.4, Gradle wrapper 4.4, Android Gradle 3.1.4.
With Android Studio 3.5+ you can set default falvors:
android {
flavorDimensions "stage", "target"
productFlavors {
develop {
getIsDefault().set(true) // that does the magic
dimension "stage"
...
When using KTS it lookes like this:
android {
flavorDimensions("stage", "target")
productFlavors {
create("develop") {
isDefault = true
dimension("stage")
...
Change the order in which you define them in productFlavors. The IDE always loads the first flavor it finds there as the default.
What actually worked for me is enabling "Android Studio Preferences -> Experimental -> Only sync the active variant". It keeps the selected build variant when reopening AS or when re-syncing, basically solving the original problem.
AS/AGP v4.1.
To make development faster, I want to do the following:
android {
defaultConfig {
resConfigs "en"
}
}
My app has a lot of languages, and doing this saves significant time while developing. However, I do NOT want to release a version with this set. Unfortunately, resConfigs is not available on product flavors or build types, so I can't set it in debug {}, for example.
How can I automatically exclude resConfigs from release variants? I do not want to have to remember comment out that line of code when I'm building for release.
Wouldn't this work?
Detect the debug build, reset the configurations and add your desired debug configuration.
applicationVariants.all { variant ->
if (variant.buildType.name == "debug") {
variant.mergedFlavor.resourceConfigurations.clear()
variant.mergedFlavor.resourceConfigurations.add("en")
}
}
My solution was inspired by this answer to a related question. Here's how you do it:
in app/build.gradle
// Reset `resConfigs` for release
afterEvaluate {
android.applicationVariants.all { variant ->
if (variant.buildType.name.equals('release')) {
variant.mergedFlavor.#mResourceConfiguration = null
}
}
}
This works because mResourceConfiguration is the backing field for resConfigs. Unfortunately, The Android Gradle DSL does not currently expose a method to reset resConfigs, so we're forced to access the field directly using the groovy #<fieldName> syntax. This works, even though mResourceConfiguration is private.
WARNING: this solution is a little fragile, as the Android Gradle build tools team could change the name of that field at any time, since it is not part of the public API.
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.