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

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")
}

Related

Jacoco fails on Gradle 7.0.2 and Kotlin 1.5.10

Today I updated gradle and kotlin dependencies in android studio.
The new versions are these:
kotlin_version = "1.5.10"
...
jacoco {
toolVersion = "0.8.6"
}
...
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
The test coverage report task fails with the following error:
2021-05-27T16:57:49.150+0200 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter] Executing actions for task ':consumerkit:testDebugUnitTestCoverage'.
2021-05-27T16:57:49.304+0200 [DEBUG] [org.codehaus.groovy.vmplugin.VMPluginFactory] Trying to create VM plugin `org.codehaus.groovy.vmplugin.v9.Java9` by checking `java.lang.Module`, but failed:
java.lang.ClassNotFoundException: java.lang.Module
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.codehaus.groovy.vmplugin.VMPluginFactory.lambda$createPlugin$0(VMPluginFactory.java:61)
at java.security.AccessController.doPrivileged(Native Method)
For Kotlin 1.5 you should use JaCoCo 0.8.7 instead of 0.8.6 - see https://github.com/jacoco/jacoco/pull/1164 and the full changelog at https://www.jacoco.org/jacoco/trunk/doc/changes.html
Example snippet:
// build.gradle or build.gradle.kts
jacoco {
toolVersion = "0.8.7"
}
I already had the
jacoco {
toolVersion = "0.8.7"
}
configured but it was not working anyway, what fixed the problem was to follow this comment here
In your module build.gradle switch back to:
android {
//....
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
don't worry, it won't break anything if you were not using Java 11 language features yet, AGP 7 is still compatible with JDK 8 as target.
Then you need to force AGP to use the 0.8.7 version and not the default 0.8.3 one. In your allprojects block in the root build.gradle file, add this:
allprojects {
//... other things
// workaround to fix an auto-import of a lower Jacoco version
resolutionStrategy {
eachDependency { details ->
if ('org.jacoco' == details.requested.group) {
details.useVersion "0.8.7"
}
}
}
}
and now it should work using:
AGP 7.0.X
Kotlin 1.5.X
JDK 11 (embedded with AS)
Simply doing
jacoco {
toolVersion = "0.8.7"
}
was not enough for me. I also had to override the version that Android was using so that the androidJacocoAnt dependency also uses 0.8.7. (./gradlew app:dependencies) Simply add this to your gradle too
android.jacoco.version = "0.8.7"
It's quite old thread, but these solutions did not solve my problems completely in Android project (actually written in Java - not in Kotlin), so I will add my solutions here. Maybe someone will find it helpful.
Except of updating jacoco toolVersion to 0.8.7, I also had to update execution data in my jacoco config as follows:
project.afterEvaluate {
tasks.create(name: "${unitTestTask}Coverage", type: JacocoReport,
dependsOn: [
"$unitTestTask",
":sdk:testDebugUnitTest",
":sdk:connectedCheck"
]) {
/* all jacoco custom configuration goes here... */
executionData(fileTree(dir: "$buildDir", includes: [
"jacoco/testDebugUnitTest.exec",
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
"outputs/code_coverage/debugAndroidTest/connected/*coverage.ec"
]))
}
}
in this configuration I had to add the following line:
"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec"
which wasn't there before because file with generated report used by sonar was generated in the new location. Report is generated with gradle task testDebugUnitTestCoverage. After all of that, I'm able to generate test coverage report including connected/instrumentation Android tests and regular unit tests in java via sonar.

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

Minimal working SpotBugs setup for Android Studio

How do I set up SpotBugs for Android?
I tried following the official documentation and that of the gradle plugin, but the setup for Android is incomplete and confusing, and didn't work.
I tried the following setup.
build.gradle (project):
buildscript {
repositories {
// ...
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
// ...
classpath "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.4"
}
}
build.gradle (app):
//...
apply plugin: "com.github.spotbugs"
android {
// ...
sourceSets {
main {
java.srcDirs = ['src/main/java']
}
}
}
// ...
spotbugs {
toolVersion = "3.1.3"
ignoreFailures = true
reportsDir = file("$project.buildDir/findbugsReports")
effort = "max"
reportLevel = "high"
}
tasks.withType(com.github.spotbugs.SpotBugsTask) {
// What do I need to do here?
}
I tried running it with ./gradlew spotbugsMain, but the gradle task is missing.
Am I supposed to add the task manually? How do I do that?
Could you show me an example of a minimal working setup for an Android project?
I made some tests on my side and I manage to make it work like this :
1) Move the sourceSets declaration outside the android block. Leave it empty, it's just for the spotbugsMain task generation, it won't impact the global Android build.
android {
// ...
}
sourceSets {
main {
java.srcDirs = []
}
}
2) Keep your spotbugs block and configure the SpotBugsTask tasks like this :
tasks.withType(com.github.spotbugs.SpotBugsTask) {
classes = files("$projectDir.absolutePath/build/intermediates/classes/debug")
source = fileTree('src/main/java')
}
It will generate reports in app/build/findbugsReports
Important :
It only works with the ./gradlew build command, ./gradlew spotbugsMain won't work as the project must be built before
You can fix that adding an assemble dependency :
tasks.withType(com.github.spotbugs.SpotBugsTask) {
dependsOn 'assemble'
classes = files("$projectDir.absolutePath/build/intermediates/classes/debug")
source = fileTree('src/main/java')
}
Following on from ToYonos answer (9 October 2018); Use this for Android Studio 3.4 and above:
project/build.gradle
buildscript {
repositories {
google()
jcenter()
maven {
url 'https:// maven url 1'
}
maven {
url "https://plugins.gradle.org/m2/" // Add this, for SpotBugs
}
}
dependencies {
classpath '...'
// If you're using gradle 6.x, add this to use SpotBugs app version 4.0.2
classpath "gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.3.0"
// If you're using gradle 4.x or 5.x, add this to use SpotBugs app version 3.1.2
classpath "com.github.spotbugs:spotbugs-gradle-plugin:2.0.1"
}
}
project/app/build.gradle
apply plugin: 'com.android.application'
apply plugin: '...'
apply plugin: "com.github.spotbugs" // <- Add this
dependencies {
...
}
// This block is only needed for gradle 4/5 only.
// It's for SpotBugs to create a 'spotbugsMain' gradle task.
sourceSets {
main {
java.srcDirs = []
}
}
spotbugs {
ignoreFailures = true
reportsDir = file("$project.buildDir/SpotBugsReports")
effort = "max"
reportLevel = "high"
}
// Note: gradle 4/5 should use "com.github.spotbugs.SpotBugsTask"
tasks.withType(com.github.spotbugs.snom.SpotBugsTask) {
dependsOn 'assembleDebug'
classes = files("$project.buildDir/intermediates/javac") // Important to use this path
excludeFilter = file("$project/spot-bugs-exclude.xml") // Optional - Explained below
source = fileTree('src/main/java') // Only needed on gradle 4/5
reports {
// Enable HTML report only
html.enabled = true
xml.enabled = false
}
}
You can generate a report for your debug build by running the gradle task:
For gradle 6.x: ./gradlew spotbugsDebug
For gradle 5 or 4: ./gradlew spotbugsMain
It's important to use classes = files("$project.buildDir/intermediates/javac") , otherwise you'll get an error "java.io.IOException: No files to analyze could be opened" -- see Findbugs fails with "java.io.IOException: No files to analyze could be opened"
You'll also need to enable the HTML report and disable XML report, to see a human-readable format.
ignoreFailures = true is optional. When SpotBugs detects a code warning, by default it will end with "BUILD FAILED" + a report file. Setting ignoreFailures = true means the gradle task will end with "BUILD SUCCESSFUL" + a report file.
To exclude some generated classes from the analysis, setup an excludeFilter. For a sample exclude file, check here or here (same as findbugs-exclude.xml)
More information and tutorial here: https://mikedemaso.com/tech/2020-06-10-spotbugs-gradle-plugin-android/

Get Android gradle plugin & checkstyle working together / command line usage

I'm evaluating the ability of the new gradle-based build system to reproduce our current ant-based build process and, as a gradle beginner, I failed to get checkstyle running with the android gradle plugin.
Environment:
gradle 1.6 running fine on a standard java project (checkstyle check target included)
up-to-date android SDK (22.0.1 with platform tools and build tools 17)
no eclipse, no android studio, only my lovely terminal
Symptom:
The target project is https://github.com/nibua-r/LigoTextDemo and I succeeded to build it using gradle but if I naively add apply plugin: checkstyle to my build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.4.2'
}
}
apply plugin: 'android'
apply plugin: 'checkstyle'
android {
buildToolsVersion '17'
compileSdkVersion 15
testBuildType 'debug'
defaultConfig {
versionCode = 1
versionName = '1.0'
minSdkVersion 12
targetSdkVersion 15
}
buildTypes {
debug {
packageNameSuffix = '.debug'
}
}
}
then gradle check doesn't even complain on not finding the checkstyle.xml file (at the default config/checkstyle location) and returns:
:check UP-TO-DATE
BUILD SUCCESSFUL
What's needed:
First, I just need a running checkstyle target. Then, I need to automate checkstyle running as a dependency of the compilation (but lets get the chekstyle target up and running first).
Assumption:
This may be related to the fact that (from the [user guide][1]):
The Android plugin […] uses its own sourceSets
but I'm not enough gradle-efficient to understand what I'm missing there. Please, gradle Master, enlighten me with your valuable knowledge!
I got pmd, findbugs, and checkstyle working with Gradle 1.12 android plugin 0.12.+ using the following script:
apply plugin: 'checkstyle'
apply plugin: 'findbugs'
apply plugin: 'pmd'
check.dependsOn 'checkstyle', 'findbugs', 'pmd'
task checkstyle(type: Checkstyle) {
configFile file("${project.rootDir}/config/quality/checkstyle/checkstyle.xml")
source 'src'
include '**/*.java'
exclude '**/gen/**'
classpath = files()
}
task findbugs(type: FindBugs) {
ignoreFailures = true
effort = "max"
reportLevel = "high"
excludeFilter = new File("${project.rootDir}/config/quality/findbugs/findbugs-filter.xml")
classes = files("$project.buildDir/intermediates/classes/")
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml {
destination "$project.buildDir/reports/findbugs/findbugs.xml"
xml.withMessages true
}
}
classpath = files()
}
task pmd(type: Pmd) {
ruleSetFiles = files("${project.rootDir}/config/quality/pmd/pmd-ruleset.xml")
ignoreFailures = true
ruleSets = ["basic", "braces", "strings"]
source 'src'
include '**/*.java'
exclude '**/gen/**'
reports {
xml.enabled = true
html.enabled = false
}
}
Running gradle build in command line will run all code quality plugins and generate xml reports in app/build/reports/ which are then ready to be viewed or parsed by CI tools.
Someone has a great answer to solve integrating PMD, findbugs and checkstyle with Gradle for Android.
Unfortunately, the only solution for now is based on ant :
http://sethrylan.org/2013/07/14/gradle-android-findbugs.html
I wish gradle will one day allow to do as much as maven for Android.
--- Update as of October 2013
With Gradle 1.8 and Android plugin for Gradle 0.6.+, you don't need this anymore. Android sourcesets and configurations are now compatible with the java plugin and all quality plugin work out of the box.
This includes pmd, findbugs, checkstyle and classycle.
--- Update
A configuration, largely inspired from the project mentioned above, is proposed in this open source project as well, plus other tools.
To get this to work with my Android project, I had to declare the task explicitly.
Here's what worked for me:
apply plugin: 'checkstyle'
task checkstyle(type: Checkstyle) {
source 'src'
include '**/*.java'
exclude '**/gen/**'
// empty classpath
classpath = files()
}
Be mindful that the Android plugin may choose to create a task of the same name in the future or work in conjunction with the checkstyle plugin in different ways.
You can try Android Check plugin (https://github.com/noveogroup/android-check):
Checkstyle
PMD
Configuration:
buildscript {
repositories { jcenter() }
dependencies {
...
classpath 'com.noveogroup.android:check:+'
...
}
}
apply plugin: 'com.noveogroup.android.check'
You can use hardcore configuration:
check {
abortOnError true
checkstyle { config hard() }
pmd { config hard() }
}
I found by digging on the web that the Android plugin depends on java-base and not java (i.e. the sourceSets management is specific) and the checkstyle plugin rely on java. As a consequence, some gradle upstream modification are needed to get the thing done. The gradle team is working on that, as seen on twitter:
#anzix Android source sets will be soon understood by the generic code quality plugins. Work on that has already started.— Gradle Build System (#Gradleware) May 26, 2013
Take a look at the Soter Gradle plugin to semlessly add support for Findbugs, Checkstyle and PMD to Android projects.

Gradle build failing due to androidannotations plugin

I am integrating andoirdannotations into a gradle build process into a generic android project. When I attempt to build the project with the addition of apply plugin: 'androidannotations I get the following failure:
$ gradle clean
FAILURE: Build failed with an exception.
* What went wrong:
Main Manifest missing from /tmp/RunTest/src/main/AndroidManifest.xml
Note(1): I want to maintain the generic android project structure.
Note(2): I have successfully build/cleaned this project without the androidannotations plugin
build.gradle file:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.3'
classpath 'net.ealden.gradle.plugins:gradle-androidannotations-plugin:0.3.0'
}
}
apply plugin: 'android'
apply plugin: 'androidannotations'
repositories {
mavenCentral()
}
android {
def target = 'android-21'
def androidAnnotationsVersion = '2.7.1'
sourceSets {
main {
manifest {
srcFile 'AndroidManifest.xml'
}
java {
srcDir 'src'
}
res {
srcDir 'res'
}
assets {
srcDir 'assets'
}
resources {
srcDir 'src'
}
}
test {
java {
srcDir 'tests/src'
}
}
}
}
So, I've bailed out on trying to maintain the generic android project structure and forced the project directory structure into the structure noted here: http://tools.android.com/tech-docs/new-build-system/using-the-new-build-system.
As expected this resolved my Main Manifest missing from /tmp/RunTest/src/main/AndroidManifest.xml however I am still getting no joy.
Now I am getting:
MyBox:RunTest $ gradle clean
Download http://repo1.maven.org/maven2/net/ealden/gradle/plugins/gradle-androidannotations-plugin/0.3.0/gradle-androidannotations-plugin-0.3.0.pom
Download http://repo1.maven.org/maven2/org/gradle/api/plugins/gradle-android-plugin/1.1.0/gradle-android-plugin-1.1.0.pom
Download http://repo1.maven.org/maven2/net/ealden/gradle/plugins/gradle-androidannotations-plugin/0.3.0/gradle-androidannotations-plugin-0.3.0.jar
Download http://repo1.maven.org/maven2/org/gradle/api/plugins/gradle-android-plugin/1.1.0/gradle-android-plugin-1.1.0.jar
FAILURE: Build failed with an exception.
* What went wrong:
Cannot add task ':processTestResources' as a task with that name already exists.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 9.28 secs
Looks like the androidannotations plugin applies the full Java gradle plugin that creates a processTestResources task which collides with the task we are trying to create.
It's unfortunate that we used the same name, but really you do not want to apply the full Java plugin to a project using the android plugin.
The android plugin only applies the base Java plugin (which provides the ability to create Java compilation tasks but does not create the default ones created by the full Java plugin).
To be honest, our plugin does things very very differently from the regular Java and plugins that are meant to extend Java projects won't work on android projects (yet).
The first error you got looks like an issue we've had (but are having trouble reproducing) where some exception got thrown but Gradle ignored it, skipped evaluating the rest of the DSL, and kept going to trying to build. Since the sourceSets remapping was skipped, it's looking in the wrong place for the Manifest.
To integrate Android Annotations into your project add the following to your project's build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
// other classpathes like gradle here, in my case
classpath 'com.android.tools.build:gradle:1.1.0'
// APT Dependency for annotation processing
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
Then apply not androidannotation as plugin but 'android-apt' in your module's build.gradle
// apply apt plugin from global gradle file
apply plugin: 'android-apt'
and also add the following to the build file:
// Tell apt where to find sources
apt {
arguments {
androidManifestFile variant.outputs[0].processResources.manifestFile
// adjust the path to your module here
resourcePackageName 'de.company.app'
}
}
dependencies {
// Android Anotations for clean and readable code
apt "org.androidannotations:androidannotations:3.2"
compile 'org.androidannotations:androidannotations-api:3.2'
}
Then you should be able to use Android Annotations in your project.
To keep an eclipse based project structure you can adjust the folders as you already did:
android {
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
}
}
you are using wrong gradle android plugin (com.google.tools plugin developed by Google)
androidannotations plugin uses com.jvoegele.gradle.plugins.android plugin and you don't have to add it to build.gradle as androidannotations plugin will fetch it itself.
Use ADT 21 or earlier as gradle-android-plugin cannot understand version which is not integer number (1.2.2-SNAPSHOT can)
As an example you can look at the build.gradle file from
https://github.com/ealden/android-annotations-idea-test/blob/master/build.gradle

Categories

Resources