8

I have a custom view library that compiles and runs correctly on it's own (through another activity created just for testing purposes inside the library project). However when I build the library, and then import the aar into another project (open module settings->new module->existing aar..) I'm getting a runtime ClassNotFoundException - the exception is on the only gradle dependency that the library is using. Why is this happening?

Library gradle file:

    apply plugin: 'com.android.library'

    android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile 'com.googlecode.libphonenumber:libphonenumber:7.2.1'
}

The error that I'm getting:

Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.i18n.phonenumbers.PhoneNumberUtil" on path: DexPathList[[zip file..
Jon
  • 7,941
  • 9
  • 53
  • 105

1 Answers1

1

An aar dependency is not like a maven/ivy dependency in that there is no transitive dependency bundled with it in a pom or xml file. When you add a aar dependency, gradle has no way to know what transitive dependencies to fetch.

A common practice in the android world seems to be, to add transitive dependencies explicitly to your app, that uses the aar. This can get cumbersome and sort of defeats the point of a dependency management system.

There are a couple of workarounds:

1. android-maven plugin

There is a 3rd party gradle plugin that allows you to publish the aar file to a local maven repo, along with a valid pom file.

2. maven-publish plugin

You an use the standard maven-publish plugin to publish the aar to a maven repo, but you have to assemble pom dependencies yourself. For example:

publications {
    maven(MavenPublication) {
        groupId 'com.example' //You can either define these here or get them from project conf elsewhere
        artifactId 'example'
        version '0.0.1-SNAPSHOT'
        artifact "$buildDir/outputs/aar/app-release.aar" //aar artifact you want to publish

        //generate pom nodes for dependencies
        pom.withXml {
            def dependenciesNode = asNode().appendNode('dependencies')
            configurations.compile.allDependencies.each { dependency ->
                def dependencyNode = dependenciesNode.appendNode('dependency')
                dependencyNode.appendNode('groupId', dependency.group)
                dependencyNode.appendNode('artifactId', dependency.name)
                dependencyNode.appendNode('version', dependency.version)
            }
        }
    }
}

In both of these cases, once aar+pom are available in a maven repo, you can use it in your app like this:

compile ('com.example:example:0.0.1-SNAPSHOT@aar'){transitive=true}

(I'm not entirely sure how transitives work if you add a dependency as compile project(:mylib). I will update this answer for this case shortly)

Community
  • 1
  • 1
RaGe
  • 22,696
  • 11
  • 72
  • 104
  • I don't understand. That dependency is inside the library and if I change it the way you suggest it won't compile anymore. Inside my app the relevant line is: compile project(':libraryname') – Jon Jan 26 '16 at 12:39
  • Sorry, I misunderstood your question. So you imported an aar but studio added compile project() ? – RaGe Jan 26 '16 at 13:00
  • I made a library project that has a compile dependency through gradle. When I run the library project by itself it runs fine. When I import the library project into another app and try to run the app I get a runtime crash with the exception. – Jon Jan 26 '16 at 13:11
  • Can you try `project(':libraryname'){transitive = true}` ? – RaGe Jan 26 '16 at 13:40
  • If I do it like this then it will compile: compile(project(':somelibrary')) {transitive = true} but I still get the same classnotfoundexception as I got at the beginning – Jon Jan 26 '16 at 13:52
  • Just to check, what if you add the library's dependency to your app as well? – RaGe Jan 26 '16 at 13:59
  • If I add the dependency to the app (and make it a normal compile - not transitive) then it works. However, there should be a way to do this without duplicating the dependencies. – Jon Jan 26 '16 at 14:18
  • 1
    The issue is that an aar doesn't come with a pom file that describes it's dependencies. So your app won't know what dependencies to get. I did write an SO answer about generating your own pom, let me go find it. – RaGe Jan 26 '16 at 14:21
  • My confusion was that if you add a dependency as `project ` , instead of aar, I assumed gradle would resolve transitive dependencies. I will do some research and update the answer. – RaGe Jan 26 '16 at 14:24
  • This all seems to be related to this issue in the google issue tracker: https://code.google.com/p/android/issues/detail?id=55863 – Jon Jan 26 '16 at 14:35