10

我在通过 gradle 自动将依赖项添加到 eclipse android 项目时遇到问题。我对gradle只有一点经验。到目前为止,我已经用 gradle 构建了两个 java 项目。一个罐子和一个可执行罐子。这没有问题。我已经使用 eclipse 插件生成了 eclipse 项目并将依赖项添加到构建路径中。我在 gradle 脚本中添加了新的依赖项,使用 gradle eclipse 启动了 gradle,更新了我的项目,并且依赖项存在于构建路径中,我可以使用它们。这是该脚本的重要部分。

apply plugin: 'java'
apply plugin: 'eclipse'
repositories {
   mavenCentral()
}

dependencies {
   compile 'commons-io:commons-io:2.4'
}

所以,现在我结合android插件尝试了它。这是我的洞 gradle 脚本。

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}

apply plugin: 'android'
apply plugin: 'eclipse'

repositories {
mavenCentral()
}

dependencies {
compile 'org.apache.commons:commons-lang3:3.1'
}

android {
    compileSdkVersion 17
    buildToolsVersion "17"

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 17
    }
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        instrumentTest.setRoot('tests')
    }
}

如果我使用 gradle eclipse 什么都不会发生。然后我发现java插件将依赖项添加到构建路径中。所以我加了

apply plugin: 'java'

到它并得到java插件与android插件不兼容的错误。然后我找到了一个解决方案,可以将 jar 自动复制到项目的 lib 文件夹中。

def libDir = file('libs')

task copyLibs(type: Copy) {

    doFirst {
        libDir.mkdirs()
    }
    from configurations.runtime
    into libDir
}

但是这个任务也需要配置运行时的 java 插件。我需要 android 插件来创建 apk 文件,所以它不是删除 android 插件的解决方案。有人知道是否可以将依赖项添加到与 android 插件兼容的 ecipse 项目中的构建路径或 lib 文件夹中?

编辑:我的一个想法是将 java-plugin 放到 eclipse-plugin 中,这样只有在应用 eclipse 插件时才会应用它。像这样的东西:

apply plugin: 'eclipse'

eclipse{
    apply plugin: 'java'
}

但是我仍然收到java和android插件不兼容的错误。也许我理解 gradle 错误,但通常只有在我启动 eclipse 插件而不是 android 插件时才应该应用 java 插件。恐怕我对gradle的理解和经验还不够好,无法通过这种方式解决或理解为什么不可能。

4

5 回答 5

12

我的解决方案基于Rafael,因为它将依赖项复制到仅由 Android 使用的 libs 目录。但是,我进一步完全分解了引用的 AAR,以便在 Eclipse 中使用。

Gradle 构建文件

将以下内容添加到您的 Android 项目 build.gradle 的末尾:

task copyJarDependencies(type: Copy) {
    description = 'Used for Eclipse. Copies all dependencies to the libs directory. If there are any AAR files it will extract the classes.jar and rename it the same as the AAR file but with a .jar on the end.'
    libDir = new File(project.projectDir, '/libs')
    println libDir
    println 'Adding dependencies from compile configuration'
    configurations.compile.filter {it.name.endsWith 'jar'}.each { File file -> moveJarIntoLibs(file)}
    println 'Adding dependencies from releaseCompile configuration'
    configurations.releaseCompile.filter {it.name.endsWith 'jar'}.each { File file -> moveJarIntoLibs(file)}
    println 'Adding dependencies from debugCompile configuration'
    configurations.debugCompile.filter {it.name.endsWith 'jar'}.each { File file -> moveJarIntoLibs(file)}
    println 'Adding dependencies from instrumentTestCompile configuration'
    configurations.instrumentTestCompile.filter {it.name.endsWith 'jar'}.each { File file -> moveJarIntoLibs(file)}
    println 'Extracting dependencies from compile configuration'
    configurations.compile.filter {it.name.endsWith 'aar'}.each { File file -> moveAndRenameAar(file) }
    println 'Extracting dependencies from releaseCompile configuration'
    configurations.releaseCompile.filter {it.name.endsWith 'aar'}.each { File file -> moveAndRenameAar(file) }
    println 'Extracting dependencies from debugCompile configuration'
    configurations.debugCompile.filter {it.name.endsWith 'aar'}.each { File file -> moveAndRenameAar(file) }
    println 'Extracting AAR dependencies from instrumentTestCompile configuration'
    configurations.instrumentTestCompile.filter {it.name.endsWith 'aar'}.each { File file -> moveAndRenameAar(file) }
}

void moveJarIntoLibs(File file){
    println 'Added jar ' + file
        copy{
            from file
            into 'libs'
        }
}

void moveAndRenameAar(File file){
    println 'Added aar ' + file
    def baseFilename = file.name.lastIndexOf('.').with {it != -1 ? file.name[0..<it] : file.name}

    // directory excluding the classes.jar
    copy{
        from zipTree(file)
        exclude 'classes.jar'
        into 'libs/'+baseFilename
    }

    // Copies the classes.jar into the libs directory of the expoded AAR.
    // In Eclipse you can then import this exploded ar as an Android project
    // and then reference not only the classes but also the android resources :D 
    copy{
        from zipTree(file)
        include 'classes.jar'
        into 'libs/' + baseFilename +'/libs'
        rename { String fileName ->
            fileName.replace('classes.jar', baseFilename + '.jar')
        }
    }
}

使用 Gradle 构建

跑 :

"gradle clean build"

您应该在 libs 目录中找到所有依赖项和分解的 AAR。这就是 Eclipse 所需要的。

在 Eclipse 中导入

现在这是真正的好处开始的地方。从上面的 gradle 步骤生成 libs 目录后,您会注意到其中也有文件夹。这些新文件夹是您的 build.gradle 文件中分解的 AAR 依赖项。

现在很酷的部分是,当您将现有的 Android 项目导入 Eclipse 时,它​​还会检测到爆炸的 AAR 文件夹作为它也可以导入的项目!

1.导入项目的libs目录下的那些文件夹,不要导入任何 'build' 文件夹,它们是由 Gradle 生成的

2.确保对您添加的所有 AAR 项目执行项目 -> 清理。在您的工作区中,检查每个 AAR 展开的项目是否在 project.properties 中具有以下内容:

target=android-<YOUR INSTALLED SKD VERSION GOES HERE>
android.library=true

3.现在在您的主 Android 项目中,您可以使用 ADT 添加库引用,或者您可以编辑 project.properties 文件并添加

android.libraries.reference.1=libs/someExplodedAAR/

4.现在您可以右键单击您的主要 Android 项目并运行为 -> Android 应用程序

但这甚至意味着什么?

  1. 这意味着您不需要任何 Android AAR Gradle 依赖项的源代码即可在 Eclipse 中引用它的类和资源。

  2. 上面的 gradle 构建脚本获取 AAR 文件并准备它以在 Eclipse 中使用。将其添加到工作区后,您就可以专注于实际的主要 Android 项目了。

  3. 您现在可以使用 Eclipse 进行调试和开发,并使用 ADT 进行部署,并将 AAR 依赖项正确捆绑在 APK 中。当您需要进行一些特定的构建时,您可以使用 gradle。

于 2014-04-20T08:01:16.847 回答
4

最后我找到了一个适合我的解决方案。此任务将依赖项复制到项目 libs 文件夹。

task copyDependencies(type: Copy) 
{
    description = 'Copy depencies to libs. Useful for Eclipse'
    libDir = new File(project.projectDir, '/libs')
    println libDir
    println 'Adding dependencies from compile configuration'
    for(file in configurations.compile) 
    {
        println 'Added ' + file
        copy 
        {
            from file
            into libDir
        }
    }
    println 'Adding dependencies from releaseCompile configuration'
    for(file in configurations.releaseCompile)
    {
        println 'Added ' + file
        copy
        {
            from file
            into libDir
        }
    }
    println 'Adding dependencies from debugCompile configuration'
    for(file in configurations.debugCompile)
    {
        println 'Added ' + file
        copy
        {
            from file
            into libDir
        }
    }

    println 'Adding dependencies from instrumentTestCompile configuration'
    for(file in configurations.instrumentTestCompile)
    {
        println 'Added ' + file
        copy
        {
            from file
            into libDir
        }
    }
}
于 2013-05-26T18:46:19.083 回答
2

以下 gradle 任务只是将 gradle 依赖项合并到 eclipse 类路径中。将其添加到build.gradle并使用gradle gradleDep2EclipseClasspath.

  import groovy.xml.StreamingMarkupBuilder
  task gradleDep2EclipseClasspath() {
     description "Merge gradle dependencies into the eclipse class path"

     def files = ["compile", "releaseCompile", "debugCompile", "instrumentTestCompile"]
       .collect {project.configurations[it].files}
       .inject([] as Set) {result, files -> result + files}
       .asList()
       .unique()
       .grep {! it.@path.toString().contains("android-support")}

      def classpath = new XmlParser().parse(file(".classpath"))
      def libs = classpath.grep {it.'@gradle-dependency' == "true"}
      libs.each {classpath.remove(it)}

      files.collect {file ->
         new Node(null, "classpathentry", [
           "path": file.toString(),
           "kind": "lib",
           "exported": "true",
           "gradle-dependency": "true"
         ])
      }.each {classpath.append(it)}

      file(".classpath").withWriter {writer ->
         writer << new StreamingMarkupBuilder().bind { mkp.xmlDeclaration() }
         def printer = new XmlNodePrinter(new PrintWriter(writer))
         printer.print(classpath)
      }
   }
于 2014-01-31T15:05:09.853 回答
0

感谢JavaJedi 的解决方案,我使用 Gradle 的输入/输出注释创建了另一个解决方案。它基于相同的原则,但在使用上更通用(例如,您可以轻松定义类型CopyJars或的新任务ExtractAars)并允许 Gradle 决定是否需要复制文件。

于 2014-09-11T00:53:53.537 回答
0

这是我基于@JavaJedi 和@gubaer 以前的所有解决方案的解决方案。

步骤1

copyAars任务添加到 build.gradle。它将 AAR 依赖项解压缩并复制到一个特殊的文件夹“deps”,而不是“libs”,以避免与 Android Studio 和/或其他 Gradle 插件和任务发生任何冲突。之后,所有分解的 AAR 都应该作为 Android 库项目手动导入,并作为依赖项添加到 Eclipse 的主项目中。这是来自@JavaJedi 的修改解决方案。

task copyAars << {
    configurations.compile.filter { it.name.endsWith 'aar' }.each { File file -> copyAndRenameAar(file) }
}

void copyAndRenameAar(File file) {
    println 'Added aar ' + file
    def baseFilename = file.name.lastIndexOf('.').with { it != -1 ? file.name[0..<it] : file.name }

    // directory excluding the classes.jar
    copy {
        from zipTree(file)
        exclude 'classes.jar'
        into "deps/aars/exploded/" + baseFilename
    }

    // Copies the classes.jar into the libs directory of the expoded AAR.
    // In Eclipse you can then import this exploded aar as an Android project
    // and then reference not only the classes but also the android resources
    copy {
        from zipTree(file)
        include 'classes.jar'
        into "deps/aars/exploded/" + baseFilename + "/libs"
        rename { String fileName -> fileName.replace('classes.jar', baseFilename + '.jar') }
    }
}

第2步

eclipseClasspath任务添加到 build.gradle。JAR 依赖项以不同的方式添加。它们被过滤并直接添加到 .classpath 文件中,因此它们在 Eclipse 主项目中自动可用。这是来自@gubaer 的修改后的解决方案。它仅包括 JAR,不包括 AAR,并且仅来自“编译”配置,但您可以轻松添加更多配置。

task eclipseClasspath << {
    def classpath = new XmlParser().parse(file(".classpath"))
    def libs = classpath.grep { it.'@gradle-dependency' == "true" }
    libs.each { classpath.remove(it) }

    configurations.compile.filter { it.name.endsWith 'jar' }
    .collect { file ->
        new Node(null, "classpathentry", [
            "path": file.toString(),
            "kind": "lib",
            "exported": "true",
            "gradle-dependency": "true"
        ])
    }
    .each { classpath.append(it) }

    file(".classpath").withWriter { writer ->
        writer << new groovy.xml.StreamingMarkupBuilder().bind { mkp.xmlDeclaration() }
        def printer = new XmlNodePrinter(new PrintWriter(writer))
        printer.print(classpath)
    }
}

第 3 步

在 Eclipse 中安装http://marketplace.eclipse.org/content/java-source-attacher插件。之后,您将能够右键单击每个 JAR 并选择“附加 Java 源”。对于 Gradle 依赖项,根据我的经验,这在 99% 的时间内都有效。

于 2015-02-09T12:53:18.477 回答