web-dev-qa-db-fra.com

Saveur du produit: classe en double trouvée

J'ai une question très stupide, mais je suis assis ici devant mon application depuis des heures mais je ne comprends pas quel est le problème.

J'ai une Android (écrite en kotlin) et je veux créer deux versions du produit et remplacer une classe/un fichier dans la version du produit:

Donc, mon script gradle est le suivant:

apply plugin: 'com.Android.application'
apply plugin: 'kotlin-Android'


Android {
  ...
  productFlavors {
    foo {
      applicationId "com.foo"
    }
  }
}

Mes fichiers sont structurés comme suit:

 - src
    - androidTest
    - foo
      - Java
        - com
          - example
            - Bar.kt
    - main
      - Java
        - com
          - example
            - Bar.kt
    - test

Donc, fondamentalement, je voudrais remplacer Bar.kt fichier dans foo version du produit, mais d'une manière ou d'une autre cela ne fonctionne pas: il indique que la barre de classe est dupliquée.

Un indice?

30
sockeqwe

La documentation des variantes indique (c'est moi qui souligne):

Remarque: Pour une variante de build donnée, Gradle génère une erreur de build s'il rencontre deux répertoires de jeu source ou plus qui ont défini la même classe Java. Par exemple, lors de la construction d'un APK de débogage, vous ne pouvez pas définissez à la fois src/debug/Utility.Java et src/main/Utility.Java. Cela est dû au fait que Gradle examine ces deux répertoires pendant le processus de génération et renvoie une erreur de "classe en double" . Si vous voulez différentes versions de Utility.Java pour différents types de build, vous pouvez demander à chaque type de build de définir sa propre version du fichier et ne pas l'inclure dans le ensemble principal/source .

La solution est donc d'avoir sa propre version de Bar.kt par variante et l'exclure de l'ensemble source principal.

44
miensol

Comme indiqué par miensol, vous ne pouvez pas placer votre fichier dans des dossiers spécifiques à main et à la saveur et vous attendre à ce que gradle fonctionne de la même manière Android fonctionne. Mais j'ai trouvé un moyen de le faire sans duplication de code pour ne pas avoir à copier votre Bar.kt à chaque dossier de saveurs que vous avez.

Supposons donc que vous ayez trois versions dev, prod et mock. Vous voulez votre spécial moqué Bar.kt in mock mais l'implémentation normale dans les versions dev et prod. Vous placez votre fichier simulé dans le dossier mock spécifique à la saveur mock/Java/com/something/ et vous mettez votre implémentation "par défaut" dans un nouveau dossier avec un nom aléatoire comme non-mock/Java/com/something/ le nommer quelque chose comme "commun" aurait également du sens. Maintenant, vous devez dire à gradle où ces saveurs doivent rechercher leur Bar.kt classe.

Mettez ceci dans votre build.gradle:

Android {
    ...
    sourceSets {
        prod {
            Java.srcDirs('src/non-mock/Java')
        }
        dev {
            Java.srcDirs('src/non-mock/Java')
        }
    }

}
16
Semanticer

Si vous avez plusieurs saveurs, comme A, B et C

et votre code principal contient toutes les activités, et pour la saveur A et C, vous souhaitez modifier certaines fonctionnalités de certaines activités ex- ShoppingCartActivity

alors vous devez apporter quelques modifications comme ci-dessous, mettre ShoppingCartActivity dans les trois versions (y compris B également) et supprimer du principal et déclarer le fichier dans tous fichier manifeste autre que le manifeste principal

pour plus de détails, vérifiez Build with source sets

- A
  - Java
    - com
      - example
        - ShoppingCartActivity.kt(some changes)

- B
  - Java
    - com
      - example
        - ShoppingCartActivity.kt

- C
  - Java
    - com
      - example
        - ShoppingCartActivity.kt(new changes added)

- main
  - Java
    - com
      - example
        **(remove from here)**
5
Vivek Hande