Android Studio Gradle: how to get variant/flavour in custom assets processor task - android-studio

I have simple assets processing gradle task prepare_assets in Android Studio 3.1.3. It is linked to preBuild task:
preBuild.dependsOn(prepare_assets)
Now I have several flavors for different resolution versions and I want to let prepare_assets know what assets to process. Maybe I don't get the idea of Gradle, but I can't understand how to achieve this: I tried to set variable in config phase
applicationVariants.all { variant ->
buildType = variant.buildType.name // sets the current build type
}
but when I read variable in my task it always the same.

In flavours section declaration:
all { flavor ->
task("${flavor.name.capitalize()}_prepare_assets") {
println "*** conf TEST for ${flavor.name.capitalize()}***"
doLast {
println "*** action TEST ${flavor.name.capitalize()}***"
if (flavor.name.equals("fullhd"))
{
//WARNING: to call copy, javaexec closures here use project.copy and project.javaexec!
}
else
{
...
}
}
}
}
In the bottom of file adding dependenses for runtime created android tasks for all flavors:
tasks.whenTaskAdded { theTask ->
if (theTask.class.name.contains("AppPreBuildTask_Decorated"))
{
for (Iterator iterator = android.productFlavors.iterator(); iterator.hasNext();) {
String flv_name = iterator.next().name.capitalize();
if (theTask.name.contains(flv_name+"Debug") || theTask.name.contains(flv_name+"Release"))
theTask.dependsOn "${flv_name}_prepare_assets";
}
}
}

Related

How do I get file outputs of gradle task

I want to create a gradle task in Android Studio that will do something with the output of the build task of another project
task foo {
dependsOn ':someApp:build'
...
copy results of :someApp:build to another location
...
}
I can't just hardcode a path as I won't know if someApp was built as debug or release and the output paths will vary based on the type of build.
dynamic copy task without using hardcoded path.
applicationVariants.all {
variant->
variant.outputs.each { output ->
println("..a")
task "copy${variant.buildType.name}"(type:Copy){
println("${variant.buildType.name}")
dependsOn app:assembleDebug
copy {
from "$buildDir\\outputs\\apk\\${variant.buildType.name}\\app-${variant.buildType.name}.apk"
into "C:\\Users\\rkumar8\\AndroidStudioProjects\\MyApplication\\app\\build\\outputs\\apk\\"
}
// you can add multiple copy if required, i am doing it here release build was named app-release-unsigned.apk
copy {
from "$buildDir\\outputs\\apk\\${variant.buildType.name}\\app-${variant.buildType.name}-unsigned.apk"
into "C:\\Users\\rkumar8\\AndroidStudioProjects\\MyApplication\\app\\build\\outputs\\apk\\"
}
}
}
}
I added a task in android block of build.gradle of app module.
applicationVariants.all {
variant->
variant.outputs.each { output ->
println("..a")
task "copy${variant.buildType.name}"(type:Copy){
println("${variant.buildType.name}")
dependsOn app:assembleDebug
copy {
from "$buildDir\\outputs\\apk\\${variant.buildType.name}\\app-${variant.buildType.name}.apk"
into "C:\\Users\\rkumar8\\AndroidStudioProjects\\MyApplication\\app\\build\\outputs\\apk\\"
}
// you can add multiple copy if required, i am doing it here release build was named app-release-unsigned.apk
copy {
from "$buildDir\\outputs\\apk\\${variant.buildType.name}\\app-${variant.buildType.name}-unsigned.apk"
into "C:\\Users\\rkumar8\\AndroidStudioProjects\\MyApplication\\app\\build\\outputs\\apk\\"
}
}
}
}
There is another post for adding our task in android build path.
https://discuss.gradle.org/t/how-to-insert-my-task-into-a-pre-defined-build-android-build/29685/3

How to properly add `mock` package to Android Studio project?

I want Android Studio to recognize my mock folder by putting mock at the end of the package name while in the Android pane.
How can I achieve this?
I've tried different combinations of:
right-clicking -> new package
right-clicking -> new Java Folder
declaring sourceSets in Gradle like so:
sourceSets {
mock {
java.srcDir 'src/mock'
}
}
add Mock as a flavor
productFlavors {
mock {
applicationIdSuffix = ".mock"
dimension "default"
}
prod {
dimension "default"
}
}
// Remove mockRelease as it's not needed.
android.variantFilter { variant ->
if (variant.buildType.name == 'release'
&& variant.flavors[0].name == 'mock') {
variant.ignore = true
}
}

Why does Android Studio not run my generateConfig but command line does

I'm trying to generate identical assets for each of the subprojects in a project. Since exactly the same thing has to happen for each subproject, I'm trying to avoid having to add the generation code to each subproject.
What I've got so far is:
// in my outer build.gradle
allprojects { proj ->
gradle.projectsEvaluated {
def configTemplate = project.file('src/main/templates/configuration.json')
def android = proj.getProperties()['android']
if (configTemplate.exists() && android != null) {
task generateConfigFiles(type: ConfigureTask) {
template configTemplate
environments proj.rootProject.file('scripts/environments.json')
environmentName host
destination new File(project.buildDir, 'templates/configuration.json')
}
android.applicationVariants.all { variant ->
variant.mergeAssets.dependsOn generateConfigFiles
}
}
}
}
// each application build.gradle
android {
sourceSets {
main {
assets.srcDir 'build/templates'
}
}
}
This seems to work exactly as expected when I run gradle from the command line ./gradlew mergeQaDebugAssets runs the generateConfigFiles task before running mergeQaDebugAssets
If I attempt to run this from Android Studio using the gradle window, it never runs generateConfigFiles
I've also gotten it to work by just including the projectsEvaluated step in each of the project build.gradle files, but, as noted, I'm trying to avoid the code duplication and maintenance headaches that brings.

Edit property based on library variant gradle android

I have an android project with native part in it. I would like to build my native code with different flags, depending on buildType and productFlavor, for instance:
android {
project.ext.buildFlags = ['-j16', 'all']
buildTypes {
debug { project.ext.buildFlags.add('NDK_DEBUG=1')}
}
productFlavors {
pretty {project.ext.buildFlags.add('PRETTY')}
ugly {project.ext.buildFlags.add('UGLY')}
}
task buildNativeCode(type: Exec) {
commandLine 'ndk-build', project.ext.buildFlags
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
}
So, for uglyDebug I would like to build my native library with 'UGLY', and 'NDK_DEBUG' flags, prettyDebug with 'PRETTY' and 'NDK_DEBUG' flags and so on. However, they are always added, regardless of the chosen configuration. From what I gather, this is done during project evaluation and I don't know how to set it up properly. For now I ended up creating many buildNativeXXX tasks that have pretty much the same content. I would love to avoid code repetition.
You can use the following commands to modify any tasks afterwards:
afterEvaluate {
productFlavors.each { productFlavorName ->
buildTypes.each { buildTypeName ->
project.ext.buildFlags.add('NDK_DEBUG=1')
if (productFlavorName.equals("pretty")) {
//enter code here
project.ext.buildFlags.add('PRETTY')
} else {
project.ext.buildFlags.add('UGLY')
}
}
}
}
Now you have full control of how gradle adds the buildFlags for you. :)
If you want to use the buildConfig variables, you can set them using:
applicationVariants.all { variant ->
variant.buildConfigField "String", "COMMIT_HASH", "HASH123456789"
}

How to access a Gradle configurations object correctly

First off, this is my first foray into Gradle/Groovy (using Gradle 1.10). I'm setting up a multi-project environment where I'm creating a jar artifact in one project and then want to define an Exec task, in another project, which depends on the created jar. I'm setting it up something like this:
// This is from the jar building project
jar {
...
}
configurations {
loaderJar
}
dependencies {
loaderJar files(jar.archivePath)
...
}
// From the project which consumes the built jar
configurations {
loaderJar
}
dependencies {
loaderJar project(path: ":gfxd-demo-loader", configuration: "loaderJar")
}
// This is my test task
task foo << {
configurations.loaderJar.each { println it }
println configurations.loaderJar.collect { it }[0]
// The following line breaks!!!
println configurations.loaderJar[0]
}
When executing the foo task it fails with:
> Could not find method getAt() for arguments [0] on configuration ':loaderJar'.
In my foo task I'm just testing to see how to access the jar. So the question is, why does the very last println fail? if a Configuration object is a Collection/Iterable then surely I should be able to index into it?
Configuration is-a java.util.Iterable, but not a java.util.Collection. As can be seen in the Groovy GDK docs, the getAt method (which corresponds to the [] operator) is defined on Collection, but not on Iterable. Hence, you can't index into a Configuration.

Resources