I'm trying to separate my android application into several modules. For instance I want to have 2 extra modules - Core and ViewModels. Both of them are pure java modules. However I'm having troubles when adding Dagger 2 dependencies to those java modules. Here's the build gradle file of one of the modules
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.dagger:dagger:2.15'
annotationProcessor 'com.google.dagger:dagger-compiler:2.15'
implementation 'org.greenrobot:eventbus:3.1.1'
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
However, when I sync the gradle I get the following error
Could not find method classpath() for arguments [com.neenbedankt.gradle.plugins:android-apt:1.8] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
Open File
Any ideas why is this happening?
I've resolved the issue. Here's what my final build.gradle of the custom module looks like
plugins {
id "net.ltgt.apt" version "0.15"
}
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.dagger:dagger:2.15'
apt 'com.google.dagger:dagger-compiler:2.13'
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
Dagger 2 successfuly generated necessary code and app worked like magic.
Related
I'm building an Android library (aar) in Java.
I want to add a Kotlin module to it. It works great when developing but the sources of the module are missing from the .aar file so it crushes at runtime in the application with FileNotFoundException.
The main module build.gradle looks like this:
apply plugin: "com.android.library"
apply plugin: "com.jfrog.artifactory"
apply plugin: "maven-publish"
...
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
dependencies {
implementation project(':kotlinModule')
....
}
Thre build.gradle of the module is:
apply plugin: 'java-library'
apply plugin: 'kotlin'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
sourceCompatibility = "7"
targetCompatibility = "7"
I've tried to add a source set but apparently you can't add source sets from outside your module folder.
I've tried to copy the kotlinModule.jar file into libs folder but then I need to rebuild every time I make a change to the module.
How can I make the sources of the module to be bundled into the .aar file?
If you want to add kotlinModule.aar file then you need to add some configuration in your Gradle config inside your android tag
android {
repositories {
flatDir {
dirs 'libs'
}
jcenter()
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
Also, add your .aar file name in your Gradle dependencies
dependencies {
implementation name: 'kotlinModule', ext: 'aar'
}
I have a Java module that generates some metadata for my Android app and needs to run as a regular Java application. After updating to Android Studio 3.0 (in 2.3.3 it worked as expected) I get a NoClassDefFoundError for the dependencies (in the case below for com/google/gson/GsonBuilder, the main method itself can be found).
I even tried putting the GSON Jar into the libs folder but it still throws the NoClassDefFoundError.
I assume the dependencies are not properly included. Any idea how to fix this?
The build.gradle looks like this:
apply plugin: 'java'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.code.gson:gson:2.8.1'
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
My class looks like this:
import com.google.gson.GsonBuilder;
public class myClass {
public static void main(String[] args) {
GsonBuilder builder = new GsonBuilder();
}
}
Use api instead of implementation.
From the docs
When your module configures an implementation dependency, it's
letting Gradle know that the module does not want to leak the
dependency to other modules at compile time. That is, the dependency
is available to other modules only at runtime.
Using this dependency
configuration instead of api or compile can result in significant
build time improvements because it reduces the amount of projects that
the build system needs to recompile. For example, if an implementation
dependency changes its API, Gradle recompiles only that dependency and
the modules that directly depend on it. Most app and test modules
should use this configuration.
See difference between api and implementation here for more info.
This is a problem probably related with Android Gradle plug-in. Try using compile instead of implementation in yourbuild.gradle`:
apply plugin: 'java'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.code.gson:gson:2.8.1'
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
The above is working in Android Studio 3.0 but with Android Gradle plug-in 2.3.3 in root build.gradle:
classpath 'com.android.tools.build:gradle:2.3.3'
UPDATE
I manage to make it works by adding google() to repositories block in root build.gradle. The following build.gradle is for the Java module:
apply plugin: 'java'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.code.gson:gson:2.8.1'
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
And this is my root build.gradle:
buildscript {
repositories {
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
}
}
allprojects {
repositories {
jcenter()
google()
}
}
Tested on Android Studio 3.0 with Gradle 4.1.
I use Android Studio 2.2 and Gradle in offline mode. The value of Gradle Home is /path/to/gradle/gradle-2.14.1. I can run Android project but now I want to run a Java standard class to test some Java code before using them in Android project. So I followed this answer. But when I run class, I got an error like this:
Error:Gradle: A problem occurred configuring root project 'demo'.
> Could not resolve all dependencies for configuration ':classpath'.
> Could not resolve com.android.tools.build:gradle:2.2.2.
Required by:
:demo:unspecified
> No cached version of com.android.tools.build:gradle:2.2.2 available for offline mode.
Also here is content of build.gradle of Java library:
apply plugin: 'java'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
How I can solve this problem? (I do not want to use another IDE or enabling online mode for Gradle)
You have to download com.android.tools.build:gradle:2.2.2...
And that requires internet. The package gradle-2.14.1 is not the same thing, as that is Gradle itself, and not the Android Gradle plugin.
Though, it is not clear why you have applied that plugin on a standard Java module.
All you need is
apply plugin: 'java'
In other words, Gradle simply builds Android code. It's not related to Android in anyway other than that, and you can run Java projects independent of Android if you set it up correctly.
Gradle - Java Plugin
For example,
java-code/build.gradle
apply plugin: 'java'
targetCompatibility = '1.7'
sourceCompatibility = '1.7'
test {
testLogging {
// Show that tests are run in the command-line output
events 'passed'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
}
app/build.gradle
apply plugin: 'com.android.application'
evaluationDependsOn(':java-code')
...
dependencies {
compile project(":java-code")
compile fileTree(dir: 'libs', include: ['*.jar'])
...
}
settings.gradle
include ':app', ':java-code'
I am using:
Android Studio 2.1.3
Gradle 2.14.1 (I tried with 2.14 also)
OpenJDK version "1.8.0_91"
I want to write some Unit tests with Groovy and Spock for sample Android application.
I have already read about RoboSpock.
When I am trying to run simple test:
package a.b.regex
class TestSum extends spock.lang.Specification {
def "test adding some numbers"() {
when:
def a = 5 + 4
then:
a == 9
}
}
When I try to run this test in Android Studio I have an error:
Process finished with exit code 1
Class not found: "a.b.regex.TestSum"Empty test suite.
Configurations that I used:
1)
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:2.1.3'
classpath 'org.codehaus.groovy:gradle-groovy-android-plugin:0.3.6'
}
}
apply plugin: 'groovyx.grooid.groovy-android'
// ...
dependencies {
testCompile 'org.robospock:robospock:1.0.0'
}
2)
buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:2.1.3'
classpath 'org.codehaus.groovy:groovy-android-gradle-plugin:1.0.0'
}
}
apply plugin: 'groovyx.android'
dependencies {
testCompile "org.codehaus.groovy:groovy-all:2.4.1"
testCompile "org.spockframework:spock-core:1.0-groovy-2.4"
testCompile 'org.codehaus.groovy:groovy:2.4.6:grooid'
}
From the console no tests are run at all.
With testing Java applications I have no problem.
Here is the project code where I want to use Spock: GitHub repository
Thankfully to Pieces I found the answer.
You should use the following configuration:
apply plugin: 'groovyx.android'
buildscript {
repositories {
jcenter() // or mavenCentral, etc.
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.3'
classpath 'org.codehaus.groovy:groovy-android-gradle-plugin:1.0.0'
}
}
testCompile 'org.codehaus.groovy:groovy:2.4.7:grooid'
testCompile('org.spockframework:spock-core:1.0-groovy-2.4') {
exclude group: 'org.codehaus.groovy'
exclude group: 'junit'
}
1)
This should work great other than you are using an outdated version of the groovy android plugin. The current version is 1.0.0. The error you are seeing is that you included your tests in androidTest source folder, when they should be included in the test source folder.
2)
You do not want groovy-all, and want to exclude that from the spock transitive dependencies as well.
This would look similar to
dependencies {
testCompile 'org.codehaus.groovy:groovy:2.4.7:grooid'
testCompile('org.spockframework:spock-core:1.0-groovy-2.4') {
exclude group: 'org.codehaus.groovy'
exclude group: 'junit'
}
}
Same as the problem with #1 you probably have the source under androidTest folder instead of the test folder.
The androidTest folder is for test that will run on the device, and the test folder if for tests that will run on your machines JVM.
If you reached here trying to configure for gradle 6.6 this will help you:
I stepped multiple times into this while trying to configure Spock in android having gradle 6.6, there has been multiple changes in gradle, so they made this plugin deprecated 'groovyx.android': https://github.com/groovy/groovy-android-gradle-plugin
Deprecated: This plugin has been deprecated in favor of Kotlin which has the full support of JetBrains and Google. The changes that go into each Android Plugin Version make it really hard for this plugin to keep up. As of Gradle 6.0 this plugin does not work.
Found out that gradle have a separate plugin for groovy support:
https://plugins.gradle.org/plugin/org.codehaus.groovy.android
This is the configuration for gradle 6.6 using groovy DSL for gradle
buildscript {
ext.kotlin_version = "1.3.72"
repositories {
google()
jcenter()
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "gradle.plugin.org.codehaus.groovy:groovy-android-gradle-plugin:3.0.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
And then in the app configuration:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: "org.codehaus.groovy.android"
def groovyVersion = "3.0.5"
def spockVersion = "2.0-M3-groovy-3.0"
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0'
testImplementation 'junit:junit:4.13'
testImplementation("org.codehaus.groovy:groovy:${groovyVersion}")
testImplementation("org.codehaus.groovy:groovy-all:${groovyVersion}")
testImplementation("org.spockframework:spock-core:${spockVersion}")
testImplementation("org.spockframework:spock-spring:${spockVersion}")
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
Problem:
Up until now I've been using Gradle to handle all of my dependencies, and it seems to take care of any duplicate dependencies between other Gradle modules. However, this does not seem to be the case when a duplicate dependency exists within a jar.
Question:
Considering that I have control over what goes into the jar, What is the best practices for handling these dependency conflicts using Gradle:
Do not include any external dependencies in the jar, include them in the project itself using build.gradle
Include all external dependcies in the jar, remove duplicates as they occur by removing them from the project build.gradle. (NOTE: this does not seem scalable, e.g. if there are duplicates between jars themselves.)
Something better (that hopefully handles this automatically)
EDIT: build.gradle file:
apply plugin: 'com.android.application'
android {
signingConfigs {
release { ... }
debug { ... }
}
compileSdkVersion 19
buildToolsVersion '19.1.0'
defaultConfig { ... }
buildTypes {
release { ... }
debug { ... }
}
sourceSets {
instrumentTest.setRoot('tests')
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:20.0.0'
compile project(':jarModule')
}
When importing external jars that have a dependency that you also have in your local app, you can do two things:
Convert your jar dependency to a Gradle dependency and exclude the dependency
For example:
testCompile('org.robospock:robospock:0.5.0') {
exclude module: "groovy-all" // <-- excludes groovy from robo spock
}
or
Remove the local dependency in your app and rely on the one in the .jar
For example, in your case with Gson:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:20.0.0'
compile project(':jarModule')
// compile 'com.google.code.gson:gson:2.3.1' // <-- removed
}