美文网首页
解决aar内含jar包冲突的方法

解决aar内含jar包冲突的方法

作者: tommwq | 来源:发表于2019-08-14 20:40 被阅读0次

    1 背景和问题
    最近在尝试将两个SDK集成到一个App中。这两个SDK都是以aar格式提供的,在分别集成时都可以正常工作。但如果同时使用两个SDK,编译器会报告错误:

    Execution failed for task ':transformClassesWithJarMergingForDebug'.
    > com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: com/somewhere/over/the/Rainbow.class
    

    原来这两个SDK都使用了同一个jar包,并将其打包在aar中。

    2 解决
    使用gradle和com.android.application插件编译Android工程时,gradle会将工程所依赖的aar包解压缩到目录

    build\intermediates\exploded-aar
    

    每个aar包独占一个子目录。通常发生冲突的文件会保存在libs、jars、jni等几个子目录下。找到并删除冲突文件,就可以解决编译问题。

    gradle可能会重新对aar进行解压缩,因此手动删除是不行的。观察编译的错误消息,编译错误发生在任务transformClassesWithJarMergingForDebug中。只要为它增加一个处理冲突的前置任务就行了。

    task clearDuplicatedClasses {
        doFirst {
            def buildDir = project.getBuildDir()
            def files = ["\\intermediates\\exploded-aar\\MyAar\\jars\\libs\\Abc.jar",
                         "\\intermediates\\exploded-aar\\MyAar\\jars\\libs\\Def.jar",
                         "\\intermediates\\exploded-aar\\MyAar\\jars\\libs\\Xyz.jar"]
    
            files.each {
                delete new File(buildDir, it)
            }
        }
    }
    
    project.afterEvaluate {
        project.tasks.findByName("transformClassesWithJarMergingForDebug").dependsOn(clearDuplicatedClasses)
    }
    

    transformClassesWithJarMergingForDebug是动态添加到project.tasks中的,如果直接写成

    project.tasks.transformClassesWithJarMergingForDebug.dependsOn(clearDuplicatedClasses)
    

    gradle会报告找不到任务。

    3 思考和附录
    如果我们需要在已有的jar包(或SDK)上做一些封装,并将封装后的代码作为SDK提供给客户。这时我们可以考虑构建两个版本,一个只包含封装层代码,另一个包含全部代码。以免出现jar包冲突的情况,方便客户使用。

    如果想了解一个gradle任务依赖于哪些任务,可以使用-dry-run(或-m)参数执行这个任务:

    .\gradlew.bat -m assembleDebug
    

    Android gradle plugin插件位于$home.gradle\caches\modules-2\files-2.1\com.android.tools.build\gradle-core的子目录下,名字是gradle-core-X.Y.Z.jar。这个jar包没有混淆,可以使用反编译工具查看里面的代码。编译Android工程使用的很多任务都定义在里面。

    使用gradle编译时,很多任务是动态添加的。要了解有project包含了哪些任务,以及这些任务对应的类,可以在build.gradle里增加一个任务

    task listAllTasks {
        doFirst {
            println("========================================")
            getProject().getTasks().forEach { task ->
                print(task.getName())
                print("\t")
                println(task.getClass().getName())
            }
            println("========================================")
        }
    }
    

    如果要查看某个特定任务对应的类,可以用

    task printTaskClass {
        doFirst {
            println("========================================")
            println(getProject().getTasks().findByName("prepareDebugDependencies").getClass())
            println("========================================")
        }
    }
    

    4 编辑记录
    2019年07月30日 建立文档。

    相关文章

      网友评论

          本文标题:解决aar内含jar包冲突的方法

          本文链接:https://www.haomeiwen.com/subject/gdznjctx.html