从 Gradle 依赖项中排除 .class 文件

Posted

技术标签:

【中文标题】从 Gradle 依赖项中排除 .class 文件【英文标题】:Excluding .class files from Gradle dependency 【发布时间】:2014-07-03 20:30:49 【问题描述】:

我正在尝试使用 gradle 将 https://github.com/Kickflip/kickflip-android-sdk 导入到我的 android 构建中,我得到了:

意外的***异常: com.android.dex.DexException:多个dex文件定义了Lorg/apache/commons/codec/binary/Base64;

Commons.codec 是我的项目的依赖项,但不直接依赖于 kick-flip 项目,我认为它来自其中包含的一个 jar。如果我打开 Kickflip 的 classes.jar,我可以看到 .class 文件。

如何排除 Base64.class 从 kickflip 导入到最终版本?我已经研究过使用 ziptree 来排除事物,但无法让任何东西发挥作用。

谢谢

我的 build.gradle 是:

apply plugin: 'android'

android 
    compileSdkVersion 19
    buildToolsVersion "19.0.3"

    defaultConfig 
        minSdkVersion 10
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    
    buildTypes 
        release 
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        
    

    compileOptions 
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    

    packagingOptions 
        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/dependencies.txt'
        exclude 'META-INF/LGPL2.1'
        exclude 'META-INF/ASL2.0'
    

    android.applicationVariants.all variant ->
        // This is an annoying hack to get around the fact that the Gradle plugin does not support
        // having libraries with different minSdkVersions. Play Services has a min version of 9 (Gingerbread)
        // but Android Maps Utils supports 8 (Froyo) still
        variant.processManifest.doFirst 
        File manifestFile = file("$buildDir/exploded-aar/io.kickflip/sdk/0.9.9/AndroidManifest.xml")
            if (manifestFile.exists()) 
                println("Replacing minSdkVersion in Android Maps Utils")
                String content = manifestFile.getText('UTF-8')
                content = content.replaceAll(/minSdkVersion="18"/, 'minSdkVersion=\"10\"')
                manifestFile.write(content, 'UTF-8')
                println(content)
            
        
    


dependencies 
    compile 'com.android.support:support-v4:19.1.0'
    compile 'io.kickflip:sdk:0.9.9'
    compile fileTree(dir: 'libs', include: '*.jar')
    compile project(':libs:typeface-textview:library')
    compile project(':libs:gpuimage')
    compile 'com.google.android.gms:play-services:4.3.23'
    compile 'com.nineoldandroids:library:2.4.0'
    compile 'com.koushikdutta.urlimageviewhelper:urlimageviewhelper:1.0.4'
    compile ('fr.avianey:facebook-android-api:3.14.0') 
      exclude module: 'support-v4'
    
    compile 'com.github.japgolly.android:svg-android:2.0.1'
    compile 'org.scribe:scribe:1.3.5'
    compile 'commons-codec:commons-codec:1.8'

【问题讨论】:

我看到 kickflip 需要最低 android sdk 版本 18。而您的构建文件定义了 minSdkVersion 10。这可能是个问题。 我也尝试构建它。他们似乎在说必须使用构建工具 19.1,并且说要从 Gradle 命令行构建。我在 Android Studio 上,所以这些示例只是抱怨 gradle 版本太旧而无法支持。 Eclipse 的简单下载按钮已从 developer.android.com 中删除。 我之前在 Eclipse 中遇到过多个 dex 错误,这通常与不正确的库链接或可能包含多次的库有关。这也许就是他们建议使用 Gradle 命令行构建的原因。 Unable to execute dex: Multiple dex files define Lcom/myapp/R$array;的可能重复 如果对您有帮助,请将答案标记为已接受。谢谢 【参考方案1】:

问题可能是 Base64 类包含两次。它位于“google-http-client”(view it)中。尝试排除此类。如果幸运的话,作为一个 Util 类,它不会在代码中使用。

在你的 build.gradle 中试试这个:

package com.google.api.client.util;

 sourceSets 
     main 
         java 
             exclude 'com.google.api.client.util.Base64.java'
             exclude 'org.apache.commons.codec.binary.Base64.java'
         
     

注意:我还没有尝试过,但听起来很有可能

【讨论】:

以上是关于从 Gradle 依赖项中排除 .class 文件的主要内容,如果未能解决你的问题,请参考以下文章

Android Studio - Gradle 实现 (...) exclude ... 不起作用(无法从依赖项中排除组)

如何从 Kotlin DSL build.gradle 中的所有依赖项中排除库?

使用 Gradle 从 jar 中排除文件

如何排除从项目依赖项中扫描的 Spring bean?

Gradle - 排除嵌套的传递依赖

使用 Gradle 时如何排除传递依赖项的所有实例?