Including a java project into an android library project does not include transitive file dependencies

The java-common module has this in build.gradle:

apply plugin: 'java'
  dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

The android module has this in build.gradle:

apply plugin: 'com.android.library'
  dependencies {
    compile project(':java-common')
    // FIXME why is this not included as a transitive dependency of :java-common?
    compile fileTree(dir: new File(project(':java-common').projectDir, 'libs'), include: ['*.jar'])
}

Including an android library module into another android library module does not have this problem. Only java into android library.

My guess is that is a capability added by the Android plugin to resolve transitive file collection dependencies within a single multi-project Android build.

Thanks for taking a look Mark. Can I mark the dependency on java-common with something to include transitive dependencies?

I’ve tried this with no luck.

dependencies {
    compile(project(':java-common')) {
      transitive = true
    }
}

I don’t believe so. Is there any reason you can’t also package it as an AAR?

java-common needs to be packaged as a JAR because it’s shared between Java and Android apps.

I guess I’m wondering, Maven-style dependencies work perfectly for transitive dependencies. Only the fileTree dependency is broken. That seems strange, that one type of dependency works but not the other.

For example, here is the full dependency list in java-common:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
      compile 'commons-logging:commons-logging:1.2'
      compile 'com.google.guava:guava:18.0'
    compile 'com.google.code.findbugs:jsr305:3.0.0'
    compile 'com.google.code.gson:gson:2.3.1'
    compile 'io.reactivex:rxjava:1.0.5'
      testCompile 'junit:junit:4.12'
    testCompile 'org.apache.commons:commons-math3:3.4.1'
}

The android module gets everything except the fileTree.

Yes, like I said, Gradle does not export file collection dependencies transitively. I assume this is a feature that the Google Android team added specifically to Android projects based on the prevalence of usage of non-managed dependencies.

I see no reason why you cannot bundle both a jar and aar. Have you tried applying both the java and android library plugins? You might also have to explicitly call the ‘jar’ task in that instance.

apply plugin: 'com.android.library'
apply plugin: 'java'

Gives an error

FAILURE: Build failed with an exception.
  * What went wrong:
A problem occurred configuring project ':android'.
> The 'java' plugin has been applied, but it is not compatible with the Android plugins.

So it seems the Android plugin “applies” the java plugin but removes most of the existing conventions that he java plugin adds, including the jar task. You could add a jar task to a library project like so:

android.libraryVariants.all { variant ->

task “${variant.name}Jar”(type: Jar) {

from variant.javaCompile

}

}

There are still some unanswered questions though if you then intend to publish that jar to an artifact repository. Not sure what kind of hooks the Android plugin might additionally add that would affect that process. Also, that jar will additionally include some of the auto generated Android classes, but that shouldn’t cause a problem for Java applications since they don’t import anything from the Android SDK.

Packaging a project that is not an android library as an android library to get transitive file dependencies to work is a workaround to begin with, so my gut is that if it doesn’t work for an easy case, it’s going to be painful to maintain.

I would like to see (or have the option to enable) transitive file dependencies work like maven dependencies.

I apologize, I misspoke originally when I said Gradle core doesn’t support this use case. It seems Gradle does export file collection dependencies in project dependencies. I was also able to reproduce the issue you describe above in Android Studio. This indicates to me there might be an issue with the Android plugin in how it treats project dependencies depending on the type of the project. You may want to post something on the adt-dev mailing list.

Ok, I’ll look into that. I think it is the plugin because the IDE is actually able to resolve the transitive dependencies. When it comes time to build, it fails. My understanding is the IDE uses something custom based on the build.gradle for interactive development, then invoke Gradle for the build.

Correct. Android Studio is heavily customized and integrated with Gradle. It’s compilation is completely delegated to Gradle.