androidandroid-gradle-plugindependenciestransitive-dependency

Android Studio Gradle not using transitive dependencies


Having experienced this problem in a separate project, I made a test project to verify the issue.

  1. Opening Android Studio 3.0, I created a new basic project. Its main module was called app.
  2. I added a library module, called libraryone.
  3. In libraryone, I added a dependency to Gson, and added a single class with a single static method using Gson.
  4. In app, I added a dependency to libraryone. I tested it plain, as well as with transitive = true, as the internet seemed to vaguely concur that doing so might help. (It did not.)
  5. In app, in MainActivity, I used the class from libraryone. This worked (as long as I didn't have transitive = false set, instead).
  6. However, I cannot reference Gson from MainActivity itself. It gives a "Cannot resolve symbol 'Gson'" error, both from Android Studio, as well as from the command line Gradle. This is...unusual and aggravating, as it means you have to repeat common dependencies all throughout a group of projects, and the classes are included in the output anyway. Surely either I'm doing something wrong, or this is a bug?

My code is as follows:

MainActivity.java (in app)

package com.erhannis.test.dependencytest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.erhannis.test.libraryone.LibClass;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String s = LibClass.convert(new Object());
        System.out.println("out: " + s);

        new com.google.gson.Gson(); // This line gives a compile-time error: "Cannot resolve symbol 'Gson'"
    }
}

LibClass.java (in libraryone)

package com.erhannis.test.libraryone;

import com.google.gson.Gson;

public class LibClass {
    public static String convert(Object o) {
        Gson gson = new Gson();
        return gson.toJson(o);
    }
}

build.gradle (app)

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.erhannis.test.dependencytest"
        minSdkVersion 18
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    implementation (project(path: ':libraryone'))
}

build.gradle (libraryone)

apply plugin: 'com.android.library'

android {
    compileSdkVersion 26
    defaultConfig {
        minSdkVersion 18
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:26.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

    implementation 'com.google.code.gson:gson:2.8.2'
}

Solution

  • It is because you declared the transitive dependency as implementation. Use api instead of implementation change:

    implementation 'com.google.code.gson:gson:2.8.2'
    

    to:

    api 'com.google.code.gson:gson:2.8.2'
    

    The reason why you should declare the transitive dependency in your library can be found here