web-dev-qa-db-fra.com

Android Créez votre projet avec des sous-projets

Je suis actuellement en train de convertir l'un de nos projets en Gradle de maven. La structure du dossier est la suivante:

gitRoot
    settings.gradle
    build.gradle
    ProjectA
        build.gradle
        src/main/Java
    Libraries
        SomeLib (git submodule)
        ProjectBRoot (git submodule)
            settings.gradle
            build.gradle
            ProjectB
                build.gradle
                src/main/Java
            Libraries
                FacebookSDK/facebook
                    build.gradle
                    src

Alors déjà, ça a l'air compliqué. Mais l’idée est que ProjectB est un projet de bibliothèque et qu’il devrait pouvoir être construit et empaqueté séparément, c’est pourquoi il a ses propres settings.gradle et, autant que je sache, il semble bien fonctionner, je le construis et sa découverte facebook très bien.

Le ProjectB/build.gradle contient cette ligne

compile project(':libraries:facebook-Android-sdk:facebook')

Le ProjectBRoot/settings.gradle contient cette ligne

include ':ProjectB', ':libraries:facebook-Android-sdk:facebook'

Le gitRoot/settings.gradle contient cette ligne

include ':ProjectA', ':Libraries:ProjectBRoot:ProjectB'

Le ProjectA/build.gradle contient cette ligne

compile project(':Libraries:ProjectBRoot:ProjectB')

Quand je lance la construction, j'obtiens cette erreur

The TaskContainer.add() method has been deprecated and is scheduled to be removed in Gradle 2.0. Please use the create() method instead.

FAILURE: Build failed with an exception.

* Where:
Build file '/gitRoot/Libraries/ProjectBRoot/ProjectB/build.gradle' line: 17

* What went wrong:
A problem occurred evaluating project ':Libraries:ProjectBRoot:ProjectB'.
> Project with path ':libraries:facebook-Android-sdk:facebook' could not be found in project ':Libraries:ProjectBRoot:ProjectB'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 4.652 secs

Donc, je suppose que ce qui ne va pas, c'est que Facebook n'est pas dans un sous-dossier direct de ProjectB ... mais cela n'a pas d'importance lors de la construction dans ProjectBRoot. Cela est probablement dû au fait que je fais directement référence à ProjectB et non par le biais de ProjectBRoot/gradle.build, mais j’ai essayé de le faire et cela n’a pas fonctionné. Quelqu'un peut-il m'aider s'il vous plaît, j'ai parcouru la documentation et il ne parle pas de plusieurs projets qui ont leurs propres fichiers settings.gradle et je pense que c'est la chose qui me dérange.

Mise à jour:

J'ai donc suivi la réponse de Xav et je suis maintenant capable de construire avec la ligne de commande mais je ne peux pas importer/construire avec Android studio. Je sais que le problème est toujours lié au projet facebook. L'erreur Je comprends, c'est qu'il ne pouvait pas configurer ProjectB.

 Gradle: A problem occurred configuring project ':ProjectA'.
   > Failed to notify project evaluation listener.
     > A problem occurred configuring project ':Libraries:ProjectBRoot:ProjectB'.
       > Failed to notify project evaluation listener.
         > Configuration with name 'default' not found.

L'erreur est causée par la ligne

 compile project(':facebook-sdk')

à l'intérieur du ProjectB/build.gradle

54
Stoyan

settings.gradle doit définir tous les modules. Cela ne chargera pas d'autres settings.gradle trouvés dans l'arborescence pour charger plus de module.

Vous devrez soit

  1. définir un module pour le SDK de facebook dans le fichier settings.gradle de niveau supérieur. Oui, il est redondant avec les autres settings.gradle.

  2. publiez le projet B d'une manière ou d'une autre (ainsi que ses dépendances, dans ce cas, la bibliothèque du kit de développement logiciel (SDK) facebook), quelque part (un référentiel d'artefacts d'entreprise, par exemple) et accédez-y à partir du projet A.

Bien que # 1 soit meilleur, cela rend la dépendance de ProjectB -> Facebook délicate, car le chemin sera différent en fonction du paramètre settings.gradle utilisé. Une solution consiste à séparer le nom/chemin du module de son emplacement actuel sur le disque. cela se fait dans le fichier settings.gradle.

Dans votre fichier de niveau supérieur settings.gradle,

include 'facebook-sdk'
project(':facebook-sdk').projectDir = new File('Libraries/ProjectBRoot/Libraries/FacebookSDK/facebook')

Dans le fichier setting.gradle de votre projet B, faites de même avec le chemin relatif différent:

include 'facebook-sdk'
project(':facebook-sdk').projectDir = new File('Libraries/FacebookSDK/facebook')

Cela permet aux deux projets de définir le même module 'facebook-sdk' situé au même emplacement absolu sur le disque.

Tous les projets dépendant de ce module doivent simplement déclarer la dépendance en tant que

compile project(':facebook-sdk') 
94
Xavier Ducrohet

Ce n'est pas la réponse que vous cherchez, mais ...

J'ai passé environ 4 jours à essayer de migrer ma structure de projet complexe (un peu comme la vôtre en fait), en dégradé. En fin de compte, j'ai abandonné le concept de sous-projet dans son intégralité (car dans mon cas, cela ne fonctionnait tout simplement pas), et j'ai choisi d'utiliser l'approche du référentiel Maven local, comme décrit dans cet article: http://www.flexlabs.org/2013/06/using-local-aar-Android-library-packages-in-gradle-builds

Ainsi, dans mes projets de bibliothèque comportant des sous-projets, j’ai essentiellement créé des projets de bibliothèque complets pour chacun d’eux, puis j’ai utilisé le lien ci-dessus pour les publier dans le référentiel local maven. Ensuite, dans le projet parent, j'ai supprimé les références aux sous-projets et, dans les dépendances, je viens de référencer les bibliothèques publiées. Et ensuite, dans mon projet principal, j'ai supprimé toutes les références à des sous-projets et j'ai référencé des versions locales maven publiées de mes bibliothèques.

En fin de compte, tout fonctionne très bien, mais il a fallu un certain temps pour tout convertir. J'avais environ 6 projets de bibliothèque avec des sous-projets, des sous-projets, etc., et maintenant tout fonctionne bien.

Ce que je n’aime pas chez les systèmes comme Gradle et Maven, c’est qu’ils attendent vraiment de vous que vous changiez "comment" vous structurez votre code/vos projets. Donc, si vous migrez vers Gradle ou si vous commencez avec Gradle, le processus peut être assez frustrant. Une fois que vous l'aurez compris, la prochaine fois est beaucoup plus facile;)

5
stuckless

Je voudrais juste que l'application avec les bibliothèques soit au même niveau. Vous pouvez toujours créer et conditionner chaque bibliothèque en fonction du fichier build.gradle. Il se peut que je manque quelque chose, mais la structure n'est pas aussi importante que celle contenue dans les fichiers build.gradle. ProjectB pourrait toujours dépendre de Facebook, même s’ils se trouvent au même niveau de dossier.

4
GrkEngineer

Eu le même problème, dans mon cas, j'ai juste oublié d'ajouter le projet dans settings.gradle. Après cela, ça a marché

2
Weslor

J'ai enfin réussi à construire le projet (sans erreurs de gradation). La réponse de Xavier était très utile.

J'ai passé presque trois jours à essayer de configurer mon projet. Je sais que je suis sur le point d'être achevé, mais j'ai une exception inattendue au plus haut niveau à la toute dernière étape du processus de construction de gradle (dexDebug).

La configuration de mon projet est très similaire à celle de Stoyan, mais j'ai plusieurs projets de bibliothèques Android qui font référence à des bibliothèques compatibles avec Android. Je suggère que si vous avez des problèmes avec la compilation de votre projet racine principal (erreur disant que le support Android est déjà ajouté)), vous devez déplacer le fichier jar dans un Android projet de bibliothèque (décomposer/séparer en instance autonome).

Exemple

--| ProjectARoot
--| ProjectA (where main/Java etc are)
  --| build.gradle
--| settings.gradle
--| libraries
  --| ProjectBRoot
    --| settings.gradle
    --| ProjectB
    --| libraries
       --| Android-supports (Android lib project)
         --| libs
           --| Android-support-v4.jar
           --| Android-support-v13.jar
         --| build.gradle
       --| libA
         --| build.gradle (referencing Android-supports)'

Exemple de script de construction pour le référencement libA Android prend en charge les projets

buildscript {
  repositories {
      maven { url 'http://repo1.maven.org/maven2' }
  }
  dependencies {
      classpath 'com.Android.tools.build:gradle:0.4'
  }
}
apply plugin: 'Android-library'

dependencies {
  compile project(':Android-support')
}

Android {
  compileSdkVersion 17
  buildToolsVersion "17.0.0"

  defaultConfig {
      minSdkVersion 7
      targetSdkVersion 17
  }
}

// racine supérieure settings.gradle

include 'ProjectB', 'Android-support', ':ProjectA' (notice Project B is first than Android-support and lastly Project A)

project(':Android-support').projectDir = new File('libraries/ProjectBRoot/libraries/Android-support')
project(':ProjectB').projectDir = new File('libraries/ProjectBRoot/ProjectB')

Actuellement, lorsque je lance Gradle Build, j'obtiens cette erreur.

:ProjectA:dexDebug

UNEXPECTED TOP-LEVEL EXCEPTION:
Java.lang.IllegalArgumentException: already added: Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCompat;
at com.Android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.Java:123)
at com.Android.dx.dex.file.DexFile.add(DexFile.Java:163)
at com.Android.dx.command.dexer.Main.processClass(Main.Java:490)
at com.Android.dx.command.dexer.Main.processFileBytes(Main.Java:459)
at com.Android.dx.command.dexer.Main.access$400(Main.Java:67)
at com.Android.dx.command.dexer.Main$1.processFileBytes(Main.Java:398)
at com.Android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.Java:245)
at com.Android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.Java:131)
at com.Android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.Java:109)
at com.Android.dx.command.dexer.Main.processOne(Main.Java:422)
at com.Android.dx.command.dexer.Main.processAllFiles(Main.Java:333)
at com.Android.dx.command.dexer.Main.run(Main.Java:209)
at com.Android.dx.command.dexer.Main.main(Main.Java:174)
at com.Android.dx.command.Main.main(Main.Java:91)
1 error; aborting
:ProjectA:dexDebug FAILED
1
Mike Kuasinski