Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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'
}
like image 641
Erhannis Avatar asked Nov 09 '17 23:11

Erhannis


2 Answers

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

like image 179
Nongthonbam Tonthoi Avatar answered Nov 10 '22 18:11

Nongthonbam Tonthoi


You are using:

implementation (project(path: ':libraryone'))
implementation 'com.google.code.gson:gson:2.8.2'

Check the official doc:

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.

Here you can find a very good blog about it.

like image 7
Gabriele Mariotti Avatar answered Nov 10 '22 19:11

Gabriele Mariotti