8

I have an android .aar library built and I am trying to integrate it with one of the projects. When the app tries to open the initial screen of the .aar library where I have API call using retrofit. I am getting the below exception

java.lang.NoClassDefFoundError: Failed resolution of:Lokhttp3/OkHttpClient$Builder;

I have not obfuscated or enabled pro-guard in my .aar project.

Below are my .aar Gradle dependencies

implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.2.0'

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
Asad Ali Choudhry
  • 4,985
  • 4
  • 31
  • 36
Niranjan Sheshadri
  • 303
  • 1
  • 3
  • 6

3 Answers3

14

OK, this is a common issue. There are several ways to use an android library(aar) in other projects. For example:

  1. By importing this aar as a module into your sample project by using implementation project(':mylibrary').
  2. By uploading your aar to a maven repository(artifactory, maven local, Jitpack, etc)

Pay attention to this:

  1. If you are using number 1 above, so you will also have to add(retrofit, okhttp3, etc) to your sample project with the same version, because the aar by default doesn't include child dependencies. That's why you are getting that exception "java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/OkHttpClient$Builder'".
  2. If you are using number 2 above, so you will have to make sure that your pom.xml file includes your child dependencies, because the server needs to download and have them available in your sample project.

What do I recommend?

I recommend developers to use MavenLocal(), it replicates a real scenario before publishing your aar to a public repository like Jitpack or whatever you want.

How can I do it?

  1. Inside build.gradle of your library module:

apply plugin: 'maven-publish'

project.afterEvaluate {
    publishing {
        publications {
            library(MavenPublication) {
                setGroupId 'YOUR_GROUP_ID'
                //You can either define these here or get them from project conf elsewhere
                setArtifactId 'YOUR_ARTIFACT_ID'
                version android.defaultConfig.versionName
                artifact bundleReleaseAar //aar artifact you want to publish

                pom.withXml {
                    def dependenciesNode = asNode().appendNode('dependencies')
                    configurations.implementation.allDependencies.each {
                        def dependencyNode = dependenciesNode.appendNode('dependency')
                        dependencyNode.appendNode('groupId', it.group)
                        dependencyNode.appendNode('artifactId', it.name)
                        dependencyNode.appendNode('version', it.version)
                    }
                }
            }
        }
    }
}

Run assemble and publishToMavenLocal gradle tasks. And you'll see something like this: enter image description here

  1. In your Sample Project
allprojects {
    repositories {
        mavenLocal()
        ...
    }
}

implementation '${YOUR_GROUP_ID}:${YOUR_ARTIFACT_ID}:${YOUR_VERSION}'

  • If you haven't specified signing info, you'll get a `no configured signatory` error. Follow here to add signatory credentials: https://docs.gradle.org/current/userguide/signing_plugin.html – Codelicious Aug 01 '23 at 10:19
1

Let's assume you've built your .aar, and published it to a maven repository (artifactory, nexus, what have you) - e.g., "implementation 'com.mycompany:library:1.0@aar'". Any child dependencies need to be included in the pom.xml delivered by the server to have them available in your application.

Since you've used the "implementation" keyword, those dependencies are considered private to the .aar, and will not be listed in the pom.xml. So they will not be available in your aar, and not automatically imported into the project by gradle.

If you change to the api keyword to "api" instead of implementation, those dependencies become public, and should be listed in the generated pom.xml, and thus should be automatically imported into the project.

This is actually also true also with aar's inside modules, rather than referenced via external systems (e.g. implementation project(':mylibrary') ). If you need the dependencies of mylibrary to run the project, they need to be api.

For reference, you may want to take a look at the Android Studio Dependency Configurations Documentation.

If, however, you're manually including the arr via a files statement (e.g., implementation files('libs/my.aar')), then you don't get automatic dependency management, and you're going to have to add the libraries needed by your aar to the main project manually as well via copy and paste between the build.gradle files.

Mark
  • 2,362
  • 18
  • 34
  • Thanks for your suggestion and help @Mark. I have not published my .aar to the maven repository. It's a local module which I tried to import the library using api like this 'api project(':MyLibrary')' but didn't work. – Niranjan Sheshadri Jul 12 '19 at 05:36
  • No, within the MyLibrary module, you need to change your dependencies from implementation to API, eg, for okhttp, retrofit, etc. Then they will be "public", and available to your parent project. – Mark Jul 15 '19 at 17:18
  • Thanks, Mark I have changed my library module dependencies from module to api and re-imported the library in the project, but I have the same issue **java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/OkHttpClient$Builder'** – Niranjan Sheshadri Jul 16 '19 at 06:33
  • If you've got "api 'com.squareup.okhttp3:okhttp:3.12.0'" and you're still getting this message... have you tried turning off proguard (could be you're missing proguard rules and the class is getting stripped). – Mark Jul 16 '19 at 11:47
  • Ya, I have tried turning off the proguard and even tried adding proguard rules, but still, I have the same error message. – Niranjan Sheshadri Jul 17 '19 at 06:30
0

You can try using fat-aar to solve this https://github.com/kezong/fat-aar-android

Zhou Hongbo
  • 1,297
  • 13
  • 25