Is there a way we could get the selected build variant on the Gradle file when we compile?
I would like to use inside the dependencies task the following code:
buildVariant = awesome code to get the buildVariant selected flag
if (buildVariant == A)
compile project(':moduleA')
else
compile project(':moduleB')
Groovy supports java code so you can use something like this:
def getCurrentFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern;
if( tskReqStr.contains( "assemble" ) )
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
Matcher matcher = pattern.matcher( tskReqStr )
if( matcher.find() )
return matcher.group(1).toLowerCase()
else
{
println "NO MATCH FOUND"
return "";
}
}
source: How to get current flavor in gradle
Click on Build Variant which is at the left bottom side of Android Studio
It has a list of all build variants available
Related
I have a doNecessaryJob task that depends on preProcessing task. If a certain condition in preProcessing is true, I want to stop the sync right away. How do I do that?
Part of my gradle is here:
task preProcessing() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern
if (tskReqStr.contains("assemble"))
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
Matcher matcher = pattern.matcher(tskReqStr)
if (matcher.find()) {
// do processing here
} else {
println "Error, stopping the sync."
// !STOP THE GRADLE SYNC HERE DUE TO ERROR!
}
}
task doNecessaryJob() {
dependsOn preProcessing
// do necessary processing here that depends on variables from preProcessing task
}
I checked other solutions here in SO but all seem to point to the command line solution such as How to stop Gradle task execution in Android Studio?.
I found it. I used GradleException like so:
task preProcessing() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern
if (tskReqStr.contains("assemble"))
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
Matcher matcher = pattern.matcher(tskReqStr)
if (matcher.find()) {
// do processing here
} else {
throw new GradleException("Error, stopping the sync.") // <--- THE FIX
}
}
As part of my build script, I would like to run some Java code before the APK is packaged.
When I try to build my project, I get the error:
Error: Could not find or load main class net.bgreco.myapp.build.BuildScript
BuildScript.java is located in app/src/main/java/net/bgreco/myapp/build/.
The BuildScript.class does get compiled successfully before I receive the error message above, and I can run it from the command line with no errors.
app/build.gradle :
task runBuildScript(type: JavaExec) {
main = 'net.bgreco.myapp.build.BuildScript'
}
tasks.whenTaskAdded { theTask ->
if (theTask.name.contains('package')) {
theTask.dependsOn 'runBuildScript'
}
}
With some help from this answer, I got it working by modifying the classpath as below. I also needed to reference some of the Android libraries so I included the path to android.jar.
app/build.gradle :
task runBuildScript(type: JavaExec) {
String flavor, buildType
(flavor, buildType) = getCurrentFlavorAndBuildType()
classpath files("build/intermediates/classes/" + flavor + "/" + buildType, "${android.getSdkDirectory().getAbsolutePath()}\\platforms\\${android.compileSdkVersion}\\android.jar")
main = 'net.bgreco.myapp.build.BuildScript'
args = [flavor] // Not needed unless you want to know the current flavor from within the BuildScript
}
tasks.whenTaskAdded { theTask ->
if (theTask.name.contains('package')) {
theTask.dependsOn 'runBuildScript'
}
}
def getCurrentFlavorAndBuildType() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern;
if (tskReqStr.contains("assemble"))
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
Matcher matcher = pattern.matcher(tskReqStr)
if (matcher.find())
return [matcher.group(1).toLowerCase(), matcher.group(2).toLowerCase()]
else {
println "NO MATCH FOUND"
return ["", ""];
}
}
As per https://developer.android.com/studio/write/lint.html#snapshot we can create a Lint warning baseline file.
The problem is that I have multiple flavors, each having their own sourceSets. Some files are used in a single flavor.
When I generate the baseline file, it's always specific to a variant. Which means that it's invalid for the other variants, ie it will miss some existing issues.
I have tried putting the
lintOptions {
baseline file("lint-baseline.xml")
}
in the build and flavor blocks, but it won't generate multiple baselines.
Has anyone managed to generate flavor specific lint baseline file? And if so how?
Thanks!
I was trying the same thing and found a way of doing it.This create diff file for release and debug.You can put your custom logic in getfileName
lintOptions {
baseline file(getFileName())
checkAllWarnings true
warningsAsErrors true
abortOnError true
}
def getCurrentFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().args.toString()
println tskReqStr
if (tskReqStr.contains("Debug")) {
return "debug"
} else {
return "release"
}
}
private String getFileName(String command) {
return getCurrentFlavor() + "-lint-baseline.xml"
}
I couldn't make the above answer exactly work as I got errors when trying to define the method in the build.gradle file.
Using himanshu saluja's answer this is what worked for me.
My root project's gradle file has:
ext.getLintFileName = {
Gradle gradle = getGradle()
String taskReq = gradle.getStartParameter().getTaskRequests().args.toString()
if(taskReq.contains("Debug")) {
return "debug-lint-baseline.xml"
} else {
return "release-lint-baseline.xml"
}
}
And the sub project's gradle file inside the android block uses the value like this:
lintOptions {
baseline file(rootProject.ext.getLintFileName)
checkDependencies true
abortOnError true
absolutePaths false
}
Given that the baseline feature is on LintOptions and this one is AFAIK not capable of being variant aware, this will not work out of the box.
You could file a feature request on https://b.android.com though.
according to my GitHub sample code:
1- add the following function to your app-level build.gradle file:
def getPath() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern
String path
String fileName = "lint-baseline"
if (tskReqStr.contains("assemble"))
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else if (tskReqStr.contains("generate"))
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
else if (tskReqStr.contains("lint"))
pattern = Pattern.compile("lint(\\w+)(Release|Debug)")
if(pattern != null) {
Matcher matcher = pattern.matcher(tskReqStr)
if (matcher.find()) {
path = matcher.group(1).toLowerCase() + matcher.group(2).toLowerCase()
return "lint-baselines/${path}-${fileName}.xml"
} else {
return "lint-baselines/${fileName}.xml"
}
}
return "lint-baselines/${fileName}.xml"
}
this function creates a specific path for each build variants. you can customize the file name by changing the "fileName" variable.
2- add the following line to lintOption scop of your app-level build.gradle file:
lintOptions {
...
// Use (or create) a baseline file for issues that should not be reported
baseline file("${getPath()}")
...
}
3- run linter for each of build varients.
for example type the following command in the terminal tab of Android studio in the root of project:
gradlew app:lintMyAppRelease
app = your module name
MyAppRelease = your build varient
4- Done
My project depends on a NDK. But my NDK build is different for my projectFlavors.
I like to build and pack my dependent NDK with -DFLAVOR1 compile option defined if app's flavor1 is selected for my app. -DFLAVOR2 when flavor2 is selected and etc.
My whole app will not work correctly if app is on flavor1 and incorrectly use a NDK built on -DFLAVOR2, so the correct selection is important.
Now how we can write our build.gradle to solve this special conditional build?
I finally found a hacky approach for my problem, then I though it is better to share it here for everyone and improvement.
Step 1:
You need to provide flag from app and depend it on preBuild. Here is a sample code for doing it.Thanks How to get current flavor in gradle for function. I just modified it a little.
import java.util.regex.Matcher
import java.util.regex.Pattern
def getCurrentFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern;
if( tskReqStr.contains( ":app:assemble" ) )
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else if( tskReqStr.contains( ":app:generate" ) )
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
else
pattern = Pattern.compile("incremental(\\w+)(Release|Debug)")
Matcher matcher = pattern.matcher( tskReqStr )
if( matcher.find() )
return matcher.group(1).toLowerCase()
else
{
println "NO MATCH FOUND"
return "";
}
}
task setFlavorFlag() {
def flavorName = getCurrentFlavor();
if (!flavorName.equals("")) {
printf("Setting flag from app...\n")
def f = file("../build/conf.tmp")
if (!f.exists()) f.createNewFile()
f.write("-D${flavorName.toUpperCase()}")
}
}
preBuild.dependsOn setFlavorFlag
dependencies {
compile project(path: ':mylibrary')
}
Step 2:
Access flag from library. I did it in ndk section:
ndk {
...
def f = file("../build/conf.tmp")
if (f.exists()) {
printf("Building library for Flavor:%s\n", f.text)
ndk.CFlags.add(f.text);
f.delete()
}
}
ok. Now your app Flavor is passed with a -D option to compile of library. Here was the approach I found after 2-3 days. I'm open for all improvements for this approach.
I would like to remove all my logs commands from my java (android) project on Release build using Gradle.
I'm using regex (which is correct):
'/Logger.log[^,]+[^L]+Logger.DEBUG[^;];/g'
and the following gradle script:
task dropJavaDebugLogs << {
FileTree javaFiles = fileTree("src/main/java") {
include "**/*.java"
}
String regex = "Logger.log[^,]+[^L]+Logger.DEBUG[^;];";
javaFiles.each { File javaFile ->
content = content.removeAll(regex);
}
}
Can you tell me what i doing wrong?