gradle plugin that used data from other plugin declared in main build - android

How to use aplicationId from
apply plugin: PublishApkToUpdateServerPlugin
version = '1.0'
class PublishApkToUpdateServerPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('uploadapk') << {
logger.lifecycle("appId ${android.defaultConfig.applicationID}");
}
}
}
my problem is here android.defaultConfig.applicationID
What went wrong:
Execution failed for task ':uploadapk'.
Could not find property 'android' on task ':uploadapk'.
How to use properties declared at other plugin and used in main build script?

I'd guess you are missing a namespace in front of uploadapk like
project.task('com.externalinc:uploadapk')
and its trying to use android:uploadapk instead. Try playing around with it.

Related

How to convert a common Gradle script to Gradle Kotlin DSL?

I am stuck on converting a common Gradle script to Gradle Kotlin DSL as it applies a custom plugin on its own so that I can't somehow make it working. What I am exactly trying to achieve this;
android-defaults.gradle (Old way - working)
apply plugin: 'libraryCommonPlugin' -> the custom plugin
android {
defaultConfig {
// other stuff
}
}
And I tried to convert this to Kotlin DSL like so;
android-default.gradle.kts (New way - not working)
plugins {
id("libraryCommonPlugin") -> the custom plugin
}
android {
defaultConfig {
// other stuff
}
}
However, this doesn't compile at all and I am getting below error;
Expression 'android' cannot be invoked as a function. The function
'invoke()' is not found
Yes, I am aware of that I don't apply com.android.application plugin but when I apply it so then I am getting another error;
Caused by: org.gradle.api.plugins.UnknownPluginException: Plugin [id:
'libraryCommonPlugin'] was not found in any of the following sources:
But I don't want to have a com.android.application plugin or whatsoever with it cause both application and library scripts will benefit from the above common script like so;
a.gradle.kts
plugins {
id("commons.android-defaults")
id("com.android.library")
id("kotlin-android")
}
dependencies {
}
app.gradle.kts
plugins {
id("commons.android-defaults")
id("com.android.application")
id("kotlin-android")
}
dependencies {
}
Do you have any solution for that particular case?

How to add if condition in build.gradle? [duplicate]

I have a multi-flavored, multi-build-typed android project and I want to integrate the NewRelic plugin. But I have to apply it only for one of the customers, thus only for one product flavor.
NewRelic uses instrumentation and the plugin would generate code in other flavors if I applied the plugin there, and that is not permitted for us.
So my question is: How can I use the apply plugin: something command in the gradle file to be applied to only one of my flavors?
Use this code:
if (!getGradle().getStartParameter().getTaskRequests()
.toString().contains("Develop")){
apply plugin: 'com.google.gms.google-services'
}
getGradle().getStartParameter().getTaskRequests().toString() returns something like [DefaultTaskExecutionRequest{args=[:app:generateDevelopDebugSources],projectPath='null'}] so as stated in the comments Develop must start with an uppercase.
Tried different solutions, but none of them worked for me. This is what I came up with and seems to work as far as I tested:
build.gradle
productFlavors {
someFlavorWithGoogleGcm {
dimension "type"
applicationId "com.example.withGcm"
ext.useGoogleGcm = true
}
someFlavorWithoutGoogleGcm {
dimension "type"
applicationId "com.example.withoutGcm"
}
}
And outside the configuration, inside the build.gradle file:
android.productFlavors.each { flavor ->
if (getGradle().getStartParameter().getTaskRequests().toString().toLowerCase().contains(flavor.name) && flavor.ext.useGoogleGcm) {
println("Building flavor with Google GCM [${flavor.name}] - applying plugin")
apply plugin: 'com.google.gms.google-services'
}
}
I simply used apply plugin: 'com.google.gms.google-services' inside the flavor in app level build.gradle and it works just fine.
productFlavors {
..... your other flavors ....
yourFlv {
....
....
apply plugin: 'com.google.gms.google-services'
}
}
No extra step needed.
Define variable - def fl
Initialize variable in you Flavours (and/or builds)
productFlavors {
freeFlavour {
(...)
fl = "free"
}
paidFlavour {
(...)
fl = "paid"
}
}
Use if statement -
if (fl == "free") {
apply plugin: something
}
I found a solution, but it is not the best so far.
So I'm not sure anymore, that what I wanted to do initially is possible.
The gradle file evaluation and the choosing of the right flavor and build type is in different phases of the gradle build, so what I've done is:
I use a build parameter from the command line. When that paramerer is true, I apply the plugin, when it is not even there, I also apply it (for IDE build).
I use Jenkins, so I could write that parameter in the build job.
build.gradle file:
// First we have to attach a task to the project, which will be running first
gradle.projectsEvaluated {
preBuild.dependsOn(applyNewRelicByProperty)
}
// Then check on the parameter, which comes from the command line
task applyNewRelicByProperty {
if(!project.hasProperty('compileNewRelic')) {
// NewRelic on: 'compileNewRelic' property not set, so running from IDE.
apply plugin: 'newrelic'
} else if(project.hasProperty('compileNewRelic') && project.getProperties().get('compileNewRelic').equals('true')) {
// NewRelic on: 'compileNewRelic' property is set and it is 'true'.
apply plugin: 'newrelic'
} else {
// NewRelic off
println("No NewRelic")
}
}
And you have to run the gradle build by this:
assembleYourApp -PcompileNewRelic=true
After upgrading to Gradle 4.2, the approach by Tarps stopped working, so I ended up combining it with Erik's answer.
Set ext.useGoogleGcm for each flavour in your build.gradle:
productFlavors {
a {
...
ext.useGoogleGcm = true
}
b {
...
ext.useGoogleGcm = false
}
}
Then at the bottom of the file:
apply plugin: 'com.google.gms.google-services'
afterEvaluate {
android.productFlavors.each { flavor ->
tasks.matching {
it.name.contains('GoogleServices') && it.name.contains(flavor.name.capitalize())
}*.enabled = flavor.ext.useGoogleGcm
}
}
In the output for your assembleRelease task, you should see tasks with "GoogleServices" in the name have run for those that are true and skipped for those that are false. If your build complains about toCapitalize, you could use toLowerCase on both it.name and flavor.name.
In the case of the Google Services Gradle plugin, the following works.
apply plugin: 'com.google.gms.google-services'
afterEvaluate {
tasks.matching { it.name.contains("GoogleServices") && !it.name.contains(yourFlavorName) }*.enabled = false
}
where yourFlavorName is a capitalised string containing the name of your flavor that must apply the plugin; all other flavors don't use the plugin.
Note that the plugin is still applied to other flavors; this solution just disables the *GoogleServices* task(s) for them. That assumes that the Google Services Gradle plugin only applies changes by adding a task containing substring "GoogleServices", which might not work in the future.
To check that this works, you can check the dependencies, e.g. like so:
./gradlew app:dependencyInsight --configuration yourFlavorNameDebugCompileClasspath --dependency google | grep -i services
That should show some dependencies for yourFlavorName but not for other flavor names:
./gradlew app:dependencyInsight --configuration otherFlavorNameDebugCompileClasspath --dependency google | grep -i services

Gradle .execute method showing error after gradle update

My project was running perfect with gradle plugin version 3.0.1 after updating to version 3.4.1 I am going through sync failure.
Previously I was using wrapper 4.10.1 which is now updated to 5.1.1.
afterEvaluate(new Action<Project>() {
#Override
void execute(Project project) {
tasks.getByName("assembleRelease").doLast {
tasks.copyReleaseBuild.execute() //error is here
tasks.copyReleaseBuildToXX.execute()
tasks.copyReleaseBuildToXXXX.execute()
}
}
copyReleaseBuild task is written something like below...
task copyReleaseBuild(type: Copy) {
def releaseDir = getProjectProperty('releaseDir')
if (releaseDir?.trim()) {
//if release folder is provided
def releaseAarFile =
getProjectProperty('sourceCodeDir') + "/android-corekit/kit/build/outputs/aar/kit-release.aar"
from releaseAarFile
into releaseDir
}
task copyReleaseBuildToXX(type: Copy) {
from "./build/outputs/aar/kit-release.aar"
into "../kitwrapper/libs"
}
task copyReleaseBuildToXXXX(type: Copy) {
from "./build/outputs/aar/kit-release.aar"
into "../kitwrapperapp/libs"
}
}
I have been trying to resolve from last two days but nothing is working as I lack knowledge of groovy.
Please check error log I am getting while building the project...
It happens because you are using an updated version of gradle (check the migration to gradle v5)
The following properties and methods of TaskInternal have been removed — use task dependencies, task rules, reusable utility methods, or the Worker API in place of executing a task directly.
execute()
executer
getValidators()
addValidator()
Now you can't call the execute method directly, but you have to use the tasks dependencies to obtain the same result.
Just define in your build.gradle:
task copyReleaseBuild {
dependsOn 'assembleRelease'
//...
}
and remove this:
afterEvaluate(new Action<Project>() {
#Override
void execute(Project project) {
tasks.getByName("assembleRelease").doLast {
tasks.copyReleaseBuild.execute() //error is here
}
}
Upgrading your build from Gradle 4.x to 5.0
The following properties and methods of TaskInternal have been removed — use task dependencies, task rules, reusable utility methods, or the Worker API in place of executing a task directly.
execute()
executer
getValidators()
addValidator()
in your case seems you have dependency between tasks: copyReleaseBuild must run after assembleRelease
so, this simple build.gradle represents this dependency:
task copyReleaseBuild {
dependsOn 'assembleRelease'
doLast {
println 'run copyReleaseBuild'
}
}
task assembleRelease {
doLast {
println 'run assembleRelease'
}
}
and the command gradle copyReleaseBuild
runs both tasks:
# gradle copyReleaseBuild
> Task :assembleRelease
run assembleRelease
> Task :copyReleaseBuild
run copyReleaseBuild
BUILD SUCCESSFUL in 2s
2 actionable tasks: 2 executed

Could not find method test() for arguments on Android studio project

In my Android application, I want exclude some test cases in a package so that I used test task in build.gradle file. for example:
apply plugin: 'com.android.library'
test{
exclude '**/calltest/Summary.class'
}
If sync the project I got following exception:
* What went wrong:
A problem occurred evaluating project ':SdkModule'.
> Could not find method test() for arguments [build_4g3vf7b615x3x1p7i9ty0pt1l$_run_closure1#73d026ca] on project ':SdkModule' of type org.gradle.api.Project.
If I add apply plugin : 'java'
CONFIGURE FAILED in 1s
The 'java' plugin has been applied, but it is not compatible with the Android plugins.
Please help me on this.
Got similar problem when try to generate XML test report for my Jenkins build.
Test related settings should be in testOptions. My file:
android {
testOptions {
unitTests.includeAndroidResources = true
unitTests.all {
reports {
junitXml.enabled = true
html.enabled = false
}
}
}
Instead of
test {
exclude '**/calltest/Summary.class'
}
try in Groovy
tasks.withType(Test) {
exclude '**/calltest/Summary.class'
}
or in Kotlin DSL (build.gradle.kts)
tasks.withType<Test> {
exclude("**/calltest/Summary.class")
}

Gradle shouldRunAfter not working in Android Studio

I want to run my custom task after assembleDebug task in Android Studio.My normal build.gradle is
apply plugin: 'com.android.application'
android {
...
}
dependencies {
...
}
task printName{
println 'Hello Guffy'
}
printName.shouldRunAfter(tasks.assembleDebug)
// or printName.shouldRunAfter(assembleDebug)
// or assembleDebug.shouldRunAfter(printName)
which is not compiling.The gradle error is
Error:(36, 0) Could not get unknown property 'assembleDebug' for task set
Is assembleDebug or other tasks not available to custom tasks ? Or is there any basic error I am doing ? Thanks
Suggested by Piotr Zawadzki, putting task in quotes worked .
So the code should be like
printName.shouldRunAfter("assembleDebug")

Categories

Resources