fredmaggiowski
fredmaggiowski

Reputation: 2248

Gradle task to build Jar excluding android classes

I'm writing a simple Gradle task that should take all the intermediate classes and package them inside a .jar file, the task is inserted in a chain of gradle tasks that are used to build an Android library.

Please note that the Android library is not packaged in a *.aar archive, I have a few task that will build the jar, build a few shared object and place them in a directory.

The task I wrote so far is the following:

task createDevJarRelease(type: Jar) {
    from 'build/intermediates/classes/release'

    manifest {
        attributes 'Implementation-Title': 'MYJar library',  
            'Implementation-Version': '1.0'
    }

    archiveName "my-jar.jar"
    doLast {
        // Copy the jar in the target directory.
        copy {
            include "my-jar.jar"
            from    "build/libs/"
            into    "targetDir"
        }
    }
}

What happens is that the jar is properly created and placed in my targetDir BUT I won't be able to actually use it inside an android project, because the jar file contains, together with my classes, also other classes from android dependencies that causes clashes when included inside an Android application.

I went inside the build/intermediates/classes/release and noticed the following directory hierarchy:

build/intermediates/classes/release
    |_ android
    |  |_ arch
    |  |  |_ core
    |  |     |_ ...
    |  |  |_ lifecycle
    |  |     |_ ...
    |  |_ support 
    |    |_ ...
    |    |  |_ ...
    |    |_ ...
    |_ my
      |_ package
        |_ name
          |_ foo.class
          |_ bar.class

I've tried different solutions found online in order to exclude the classes beneath the android directory but with no success.

I tried explicitly adding the exclude command in the Gradle task above but didn't work at all (classes are still there).

exclude 'build/intermediates/classes/release/android'

The error seen when building the Application with this jar is:

> Task :app:transformDexArchiveWithDexMergerForDebug
Dex: Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Landroid/arch/lifecycle/R;
    UNEXPECTED TOP-LEVEL EXCEPTION:
    com.android.dex.DexException: Multiple dex files define Landroid/arch/lifecycle/R;

com.android.dex.DexException: Multiple dex files define Landroid/arch/lifecycle/R;
        at com.android.dx.merge.DexMerger.readSortableTypes(DexMerger.java:661)
        at com.android.dx.merge.DexMerger.getSortedTypes(DexMerger.java:616)
        at com.android.dx.merge.DexMerger.mergeClassDefs(DexMerger.java:598)
        at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:171)
        at com.android.dx.merge.DexMerger.merge(DexMerger.java:198)
        at com.android.builder.dexing.DexArchiveMergerCallable.call(DexArchiveMergerCallable.java:61)
        at com.android.builder.dexing.DexArchiveMergerCallable.call(DexArchiveMergerCallable.java:36)
        at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1424)
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
        at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)


FAILURE: Build failed with an exception.

The project dependencies are:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    implementation 'com.android.support:appcompat-v7:27.1.1'
    testImplementation 'junit:junit:4.12'
}

Upvotes: 1

Views: 992

Answers (1)

fredmaggiowski
fredmaggiowski

Reputation: 2248

The actual solution for this was not to exclude the classes in the jar gradle task but to change the dependencies of the project, using compileOnly instead of implementation when setting the com.android.support dependency.

The fix is:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
     androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compileOnly 'com.android.support:appcompat-v7:27.1.1'
    testImplementation 'junit:junit:4.12'
}

Upvotes: 1

Related Questions