android - Gradle + AndroidAnnotations 生成重复的类错误 - 需要在每次构建之前清理项目

标签 android gradle android-studio android-annotations annotation-processing

我在使用 gradle 构建将我的 IntelliJ IDEA 项目迁移到 Android Studio 时遇到问题。我已经像其他帖子中推荐的那样设置了 AndroidAnnotations 库,它工作得很好。但是,当多次编译我的项目而不执行 :clean 任务时,我收到以下错误消息:

/project-dir/build/source/apt_generated/flavor1/release/com/example/app/MyActivity_.java:15: error: duplicate class: com.example.app.MyActivity_

[more errors here...]

我相信多个系列构建失败,因为 AndroidAnnotations 总是在 :compile 任务之前重新创建 *_.java 文件(不检查是否有必要或not) 和 :compile 任务识别新文件(例如使用时间戳)但已经发现这些文件是预编译的 *.class 文件,因此抛出错误。这可能吗?我怎样才能防止这种行为?我可以为 AndroidAnnotations 添加必要性检查吗?还是其他问题?


更新 1: 似乎错误是从 AndroidAnnotations 本身抛出的,因为 :compile 在我删除 *.java 文件时起作用手动在 apt_generated 文件夹中。


更新 2:

我从我的 build.gradle 中删除了以下行:

// Automatically add the generated source code to the source set
android.sourceSets[getSourceSetName(variant)].java.srcDirs += aptOutput

我不完全知道为什么没有这条线它会工作。因为我没有使用 Android Studio 的 Mark Directory as > Sources Root 添加文件夹。可能这是缓存的结果?或者 gradle 是否以某种方式自动将我生成的 java 文件添加到类路径中?

尽管如此,如果您提出任何意见,我将不胜感激。


更新 3/解决方案

删除该行并与 Android Studio 同步 gradle 构建文件后,自动生成的源代码作为 Source Root 被删除,导致 IDE 显示缺少类的错误。

最终,我在Android Annotations github问题上找到了解决方案:https://github.com/excilys/androidannotations/issues/676

我重新添加了将其添加到源集中的语句(允许 Android Studio 将其显示为源根目录)。此外,我使用以下方法从变体源集合中删除了文件:

variant.javaCompile.source = variant.javaCompile.source.filter { p ->
    return !p.getPath().startsWith(aptOutputDir.getPath())
}

现在可以识别生成的文件,重复类错误消失了。

最好的问候, 大卫

这是我最终的 build.gradle。我希望这对你们中的一些人有所帮助:

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.5.+'
    }
}

apply plugin: 'android'

repositories {
    mavenCentral()
}

configurations {
    // This is the annotations processor dependency configuration.
    apt
}

def getSourceSetName(variant) {
    return new File(variant.dirName).getName();
}

android {
    compileSdkVersion 18

    defaultConfig {
        versionCode 10
        versionName "1.0.2"
        targetSdkVersion 17
        minSdkVersion 10
    }

    buildToolsVersion "18.0.1"

    buildTypes {
        release {
            zipAlign true
        }
    }

    productFlavors {
        flavor1 {}
        flavor2 {}
    }

    // This has to go after the productFlavors command (otherwise moving the flavor source set root fails).
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        // We move the root of our flavors to support our legacy structure.
        flavor1.setRoot('flavors/flavor1')
        flavor2.setRoot('flavors/flavor2')
    }

    applicationVariants.all { variant ->
        def aptOutputDir = project.file("${project.buildDir}/source/apt_generated")
        def aptOutput = new File(aptOutputDir, variant.dirName)

        println "****************************"
        println "variant: ${variant.name}"
        println "manifest:  ${variant.processResources.manifestFile}"
        println "aptOutput:  ${aptOutput}"
        println "****************************"

        android.sourceSets[getSourceSetName(variant)].java.srcDirs+= aptOutput.getPath()

        variant.javaCompile.doFirst {
            println "*** Running AndroidAnnotations for ${variant.name}"
            aptOutput.mkdirs()


            variant.javaCompile.options.compilerArgs += [
                    '-processorpath', configurations.apt.getAsPath(),
                    '-AandroidManifestFile=' + variant.processResources.manifestFile,
                    '-s', aptOutput
            ]
        }

        variant.javaCompile.source = variant.javaCompile.source.filter { p ->
            return !p.getPath().startsWith(aptOutputDir.getPath())
        }
}

dependencies {
    // Android-Annotations
    apt 'com.googlecode.androidannotations:androidannotations:2.7.1'
    compile 'com.googlecode.androidannotations:androidannotations-api:2.7.1'

    // Include libraries only in flavor1
    flavor1Compile fileTree(dir: 'libs', include: '*.jar')
}

这是我的(初始)build.gradle(我去掉了不相关的部分):

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.5.+'
    }
}

apply plugin: 'android'

repositories {
    mavenCentral()
}

configurations {
    // This is the annotations processor dependency configuration.
    apt
}

def getSourceSetName(variant) {
    return new File(variant.dirName).getName();
}

android {
    compileSdkVersion 18

    defaultConfig {
        versionCode 10
        versionName "1.0.2"
        targetSdkVersion 17
        minSdkVersion 10
    }

    buildToolsVersion "18.0.1"

    buildTypes {
        release {
            zipAlign true
        }
    }

    productFlavors {
        flavor1 {}
    }

    // This has to go after the productFlavors command (otherwise moving the flavor source set root fails).
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        // We move the root of our flavor to support our legacy structure.
        flavor1.setRoot('flavors/flavor1')
    }

    applicationVariants.all { variant ->
        aptOutput = file("${project.buildDir}/source/apt_generated/${variant.dirName}")
        println "****************************"
        println "variant: ${variant.name}"
        println "manifest:  ${variant.processResources.manifestFile}"
        println "aptOutput:  ${aptOutput}"
        println "****************************"

        // Automatically add the generated source code to the source set
        android.sourceSets[getSourceSetName(variant)].java.srcDirs += aptOutput

        variant.javaCompile.doFirst {
            println "*** Running AndroidAnnotations for ${variant.name}"
            aptOutput.mkdirs()

            variant.javaCompile.options.compilerArgs += [
                    '-processorpath', configurations.apt.getAsPath(),
                    '-AandroidManifestFile=' + variant.processResources.manifestFile,
                    '-s', aptOutput
            ]
        }
    }
}

dependencies {
    // Android-Annotations
    apt 'com.googlecode.androidannotations:androidannotations:2.7.1'
    compile 'com.googlecode.androidannotations:androidannotations-api:2.7.1'

    // Include libraries only in flavor1
    flavor1Compile fileTree(dir: 'libs', include: '*.jar')
}

如有任何帮助,我将不胜感激。

谢谢, 大卫

最佳答案

如果您从 Eclipse 导出 build.gradle,它会在 gradle 文件中包含 .apt_generated,但它不应该。将其取出,这些错误应该会消失。

关于android - Gradle + AndroidAnnotations 生成重复的类错误 - 需要在每次构建之前清理项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18958388/

相关文章:

java - 自定义 linting 规则因 com.android.tools.build :gradle:2. 3.0 而失败

java - 如何获取前台应用程序和/或 Activity ?

spring - 在springboot中使用gradle时,加载依赖项遇到sun.security.validator.validatorexception。我不知道怎么解决

gradle distZip 重命名存档

android - 使用 Gradle 和 CMake 将发布和调试子目录添加到 Android 构建中

java - Android Studio Activity_main.xml

Android Studio报错 ➡ Cannot run program "git"... CreateProcess error=2, 系统找不到指定的文件

android - 打开时更改 Spinner 内容

java - 为什么我会得到 ClassCastException?

android/storage/emulated/0 和/data/media/0 权限不同