2013-06-21 3 views
17

В Google IO объявлен новый алгоритм системы сборки, чтобы заменить муравьев. Мой проект использует aspectj, и я хотел бы использовать его в своем проекте. Я не мог понять некоторые переменные, чтобы заставить его работать. Я не нашел android. * Output classpath. Кто-нибудь может помочь?Новая система сборки Android (gradle) и aspectj

Вот мой текущий build.gradle:

buildscript { 
    repositories { 
     mavenCentral() 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:0.4' 
    } 
} 
apply plugin: 'android' 
sourceCompatibility = 1.6 

configurations { 
    ajc 
} 

dependencies { 
    compile fileTree(dir: 'libs', includes: ['*.jar']) 
    ajc files('build-tools/aspectjtools.jar', 'libs/aspectjrt.jar') 
} 

android { 
    compileSdkVersion 16 
    buildToolsVersion "17" 

    defaultConfig { 
     minSdkVersion 8 
     targetSdkVersion 16 
    } 
    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('test') 
    } 
} 

gradle.projectsEvaluated { 
    compileJava.doLast { 
     tasks.compileAspectJ.execute() 
    } 
    println 'lalalalala' 
} 

task compileAspectJ { 

    ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", 
     classpath: configurations.ajc.asPath) 
    ant.iajc(source: sourceCompatibility, target: sourceCompatibility, 
     destDir: "?????????????????????", 
     classpath: "????????????????????????????") { 

     sourceroots{ 
      android.sourceSets.main.java.srcDirs.each { 
       pathelement(location: it.absolutePath) 
      } 
     } 
    } 
} 

Это старый муравей код, который работает очень хорошо: http://code.google.com/p/anymemo/source/browse/custom_rules.xml

Edit:

Обновленный build.gradle в соответствии с первый ответ. Тем не менее, я, по-видимому, не признаю все библиотеки и не жалуюсь, что классы в библиотеках не найдены

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

apply plugin: 'android' 
sourceCompatibility = 1.6 
targetCompatibility = 1.6 

repositories { 
    mavenCentral() 
} 

android { 
    compileSdkVersion 18 
    buildToolsVersion "18.1.0" 

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

     // Move the tests to tests/java, tests/res, etc... 
     instrumentTest.setRoot('tests') 

     // Move the build types to build-types/<type> 
     // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ... 
     // This moves them out of them default location under src/<type>/... which would 
     // conflict with src/ being used by the main source set. 
     // Adding new build types or product flavors should be accompanied 
     // by a similar customization. 
     debug.setRoot('build-types/debug') 
     release.setRoot('build-types/release') 
    } 
} 

configurations { 
    ajc 
    aspects 
    ajInpath 
} 

ext.aspectjVersion = '1.7.3' 

dependencies { 
    compile fileTree(dir: 'libs', include: '*.jar') 

    ajc "org.aspectj:aspectjtools:${aspectjVersion}" 
    compile "org.aspectj:aspectjrt:${aspectjVersion}" 
    compile 'com.android.support:appcompat-v7:18.0.0' 
} 

android.applicationVariants.all { variant -> 

    variant.javaCompile.doLast { 
     def androidSdk = android.adbExe.parent + "/../platforms/" + android.compileSdkVersion + "/android.jar" 
    println 'AAAAAAAAAAAAAAAAA: ' + androidSdk 

     def iajcClasspath = configurations.compile.asPath + ":" + androidSdk 
     configurations.compile.dependencies.each { dep -> 
      if(dep.hasProperty("dependencyProject")) { 
       iajcClasspath += ":" + dep.dependencyProject.buildDir + "/bundles/release/classes.jar" 
      } 
     } 
    println 'BBBBBBBBBBBBBB : ' + iajcClasspath 

     ant.taskdef(resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath) 
     ant.iajc (
       source:sourceCompatibility, 
       target:targetCompatibility, 
       destDir:"${project.buildDir}/classes/${variant.dirName}", 
       maxmem:"512m", 
       fork:"true", 
       aspectPath:configurations.aspects.asPath, 
       inpath:configurations.ajInpath.asPath, 
       sourceRootCopyFilter:"**/.svn/*,**/*.java", 
       classpath:iajcClasspath 
     ){ 
      sourceroots{ 
       android.sourceSets.main.java.srcDirs.each{ 
        pathelement(location:it.absolutePath) 
       } 
       pathelement(location:"${project.buildDir}/source/r/${variant.dirName}") 
      } 
     } 
    } 
} 

Ошибки:

1 [error] The method onPrepareOptionsMenu(Menu) of type FingerPaint must override or impl[3780/18642] 
rtype method 
[ant:iajc] public boolean onPrepareOptionsMenu(Menu menu) { 
[ant:iajc]    ^^^^^^^^^^^^^^^^^^^^^^^^^^ 
[ant:iajc] /home/liberty/mp/android/AnyMemo/src/com/example/android/apis/graphics/FingerPaint.java:21 
2 [error] The method onPrepareOptionsMenu(Menu) is undefined for the type GraphicsActivity 
[ant:iajc] super.onPrepareOptionsMenu(menu); 
[ant:iajc]  ^^^^^^^^^^^ 
[ant:iajc] /home/liberty/mp/android/AnyMemo/src/com/example/android/apis/graphics/FingerPaint.java:21 
7 [error] The method onOptionsItemSelected(MenuItem) of type FingerPaint must override or implement a 
supertype method 
[ant:iajc] public boolean onOptionsItemSelected(MenuItem item) { 
[ant:iajc]    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
[ant:iajc] /home/liberty/mp/android/AnyMemo/src/com/example/android/apis/graphics/FingerPaint.java:22 
8 [error] The constructor ColorPickerDialog(FingerPaint, FingerPaint, int) is undefined 
[ant:iajc] new ColorPickerDialog(this, this, mPaint.getColor()).show(); 
[ant:iajc] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
[ant:iajc] /home/liberty/mp/android/AnyMemo/src/com/example/android/apis/graphics/FingerPaint.java:25 
4 [error] The method onOptionsItemSelected(MenuItem) is undefined for the type GraphicsActivity 
[ant:iajc] return super.onOptionsItemSelected(item); 
[ant:iajc]    ^^^^^^^^^^^^ 
[ant:iajc] /home/liberty/mp/android/AnyMemo/src/com/example/android/apis/graphics/FingerPaint.java:25 
8 [error] The method getDefaultSharedPreferences(Context) in the type PreferenceManager is not applic 
able for the arguments (FingerPaint) 
[ant:iajc] SharedPreferences shre = PreferenceManager.getDefaultSharedPreferences(this); 
[ant:iajc]    

EDIT: Это конечный файл build.gradle, который работает для моего проекта: https://code.google.com/p/anymemo/source/browse/build.gradle?spec=svnf85aaa4b2d78c62876d0e1f6c3e28252bf03f820&r=f85aaa4b2d78c62876d0e1f6c3e28252bf03f820

+0

Для вашей новой ошибки я попытался воспроизвести ее, добавив библиотеку jar, но она отлично работает для меня. – aegar

+0

Я полагаю, что ошибка не связана с самой библиотекой, так как iajc, похоже, находит вашу GraphicsActivity, но это может быть неправильный путь sdk: все ваши ошибки либо связаны с методами из активности, которые не могут быть найдены в GraphicsActivity, либо GraphicsActivity, которая не распознается как активность в конструкторах. Вы проверили androidSdk var? Mine указывает где-то в «/ home/aegar/android-sdk/platform», где у меня только Android-18. – aegar

+0

Это проблема зависимости AAR. AAR нельзя использовать в качестве банки. Вы обрабатываете dependencyProject, но если вы укажете компиляцию «com.android.support:appcompat-v7:18.0.0», class.jar находится в вложенном пакете, все банки в этом каталоге должны быть добавлены в путь к классам. – Liberty

ответ

6

Я понял, что AAR не может использоваться в качестве библиотеки jar в моем коде. Если вы используете такие зависимости, как это

compile 'com.android.support:appcompat-v7:18.0.0' 

Вам необходимо найти файл jar и добавить путь к классу. Следующий код сделает это.

tree = fileTree(dir: "${project.buildDir}/exploded-bundles", include: '**/classes.jar') 
tree.each { jarFile -> 
    iajcClasspath += ":" + jarFile 
} 

Так весь раздел будет:

variant.javaCompile.doLast { 
    // Find the android.jar and add to iajc classpath 
    def androidSdk = android.adbExe.parent + "/../platforms/" + android.compileSdkVersion + "/android.jar" 
    println 'Android SDK android.jar path: ' + androidSdk 

    def iajcClasspath = androidSdk + ":" + configurations.compile.asPath 
    configurations.compile.dependencies.each { dep -> 
     if(dep.hasProperty("dependencyProject")) { 
      iajcClasspath += ":" + dep.dependencyProject.buildDir + "/bundles/release/classes.jar" 
     } 
    } 

    // handle aar dependencies pulled in by gradle (Android support library and etc) 
    tree = fileTree(dir: "${project.buildDir}/exploded-bundles", include: '**/classes.jar') 
    tree.each { jarFile -> 
     iajcClasspath += ":" + jarFile 
    } 
     println 'Classpath for iajc: ' + iajcClasspath 

     ant.taskdef(resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath) 

Для полного примера смотрите в build.gradle для проекта AnyMemo здесь: https://code.google.com/p/anymemo/source/browse/build.gradle?spec=svnf85aaa4b2d78c62876d0e1f6c3e28252bf03f820&r=f85aaa4b2d78c62876d0e1f6c3e28252bf03f820

+0

Примечание: Использование инструментов 19 Я думаю, что они, возможно, изменили местоположение. Мне нужно было использовать «exploded-aar» вместо «взорванных пачек» из приведенного выше примера. – withoutclass

+0

withoutclass, Да, они изменили имя. https://code.google.com/p/anymemo/source/browse/build.gradle?spec=svnf85aaa4b2d78c62876d0e1f6c3e28252bf03f820&r=f85aaa4b2d78c62876d0e1f6c3e28252bf03f820 имеет это изменение. – Liberty

+0

СПАСИБО! Я пропустил этот пост и сражался с ответом, прежде чем я сдался и посмотрел сюда. Этот ответ требует большего количества оборотов. – dieend

15

Я также хотел использовать AspectJ с Gradle и Android Studio, и я, наконец, заставил его работать, но у меня все еще есть некоторые рукописные пути, которые я бы хотел заменить более универсальными вариантами градиента.

Редактировать: Я заменил все жестко закодированные абсолютные пути альтернативами на основе градиента, поэтому это решение больше не зависит от данной платформы или имени пользователя. Тем не менее, он по-прежнему использует относительные пути, которые могут измениться с IDE на другой или в дальнейших версиях Android Studio. Кроме того, я не очень доволен тем, как я нахожу android.jar.

Я первый AspectJ нагрузка:

configurations { 
ajc 
aspects 
ajInpath 
} 

ext.aspectjVersion = '1.7.3' 

dependencies { 
    compile project(":LibTest") 

    ajc "org.aspectj:aspectjtools:${aspectjVersion}" 
    compile "org.aspectj:aspectjrt:${aspectjVersion}" 
    compile 'com.android.support:appcompat-v7:18.0.0' 
} 

И затем добавить задачу, которая будет выполняться после JavaCompile задачи текущего варианта:

android.applicationVariants.all { variant -> 

    variant.javaCompile.doLast { 
     def androidSdk = android.adbExe.parent + "/../platforms/" + android.compileSdkVersion + "/android.jar" 

     def iajcClasspath = configurations.compile.asPath + ";" + androidSdk 
     configurations.compile.dependencies.each { dep -> 
      if(dep.hasProperty("dependencyProject")) { 
       iajcClasspath += ":" + dep.dependencyProject.buildDir + "/bundles/release/classes.jar" 
      } 
     } 

     ant.taskdef(resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath) 
     ant.iajc (
       source:sourceCompatibility, 
       target:targetCompatibility, 
       destDir:"${project.buildDir}/classes/${variant.dirName}", 
       maxmem:"512m", 
       fork:"true", 
       aspectPath:configurations.aspects.asPath, 
       inpath:configurations.ajInpath.asPath, 
       sourceRootCopyFilter:"**/.svn/*,**/*.java", 
       classpath:iajcClasspath 
     ){ 
      sourceroots{ 
       android.sourceSets.main.java.srcDirs.each{ 
        pathelement(location:it.absolutePath) 
       } 
       pathelement(location:"${project.buildDir}/source/r/${variant.dirName}") 
      } 
     } 
    } 
} 

Везде, где я использую ${variant.dirName}, он будет заменен либо «debug», либо «release» в соответствии с текущей конфигурацией сборки.

Добавление android.jar к пути к классу требуется для компиляции специфичных для Android классов, а для строки pathelement(location:"${project.buildDir}/source/r/${variant.dirName}") требуется использовать классы из файла автогенерации R.java.

Редактировать: Итерации над зависимостями проекта для создания iajcClasspath позволяют использовать классы из проектов ваших библиотек. configurations.compile.asPath уже содержит ссылку на ваш apklib (файл aar), который на самом деле является почтовым индексом, содержащим как банку, так и ресурсы библиотеки. Iajc не распознает эти файлы как это, но есть каталог пакетов, содержащий класс.jar для вашей библиотеки в каталоге сборки. Я использую относительный путь с «выпуском» жестко закодированным в нем, потому что библиотека имеет другой вариант, чем основной проект в моей ситуации, поэтому я не могу использовать ${variant.dirName} здесь.

Вот полная сборка.gradle file:

buildscript { 
    repositories { 
     mavenCentral() 
    } 
    dependencies { 
     classpath 'com.android.tools.build:gradle:0.5.+' 
    } 
} 
apply plugin: 'android' 

repositories { 
    mavenCentral() 
} 

android { 
    compileSdkVersion 18 
    buildToolsVersion "18.1.0" 

    defaultConfig { 
     minSdkVersion 7 
     targetSdkVersion 18 
    } 
} 

configurations { 
    ajc 
    aspects 
    ajInpath 
} 

ext.aspectjVersion = '1.7.3' 

dependencies { 
    compile project(":LibTest") 

    ajc "org.aspectj:aspectjtools:${aspectjVersion}" 
    compile "org.aspectj:aspectjrt:${aspectjVersion}" 
    compile 'com.android.support:appcompat-v7:18.0.0' 
} 

android.applicationVariants.all { variant -> 

    variant.javaCompile.doLast { 
     def androidSdk = android.adbExe.parent + "/../platforms/" + android.compileSdkVersion + "/android.jar" 

     def iajcClasspath = configurations.compile.asPath + ";" + androidSdk 
     configurations.compile.dependencies.each { dep -> 
      if(dep.hasProperty("dependencyProject")) { 
       iajcClasspath += ":" + dep.dependencyProject.buildDir + "/bundles/release/classes.jar" 
      } 
     } 

     ant.taskdef(resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath) 
     ant.iajc (
       source:sourceCompatibility, 
       target:targetCompatibility, 
       destDir:"${project.buildDir}/classes/${variant.dirName}", 
       maxmem:"512m", 
       fork:"true", 
       aspectPath:configurations.aspects.asPath, 
       inpath:configurations.ajInpath.asPath, 
       sourceRootCopyFilter:"**/.svn/*,**/*.java", 
       classpath:iajcClasspath 
     ){ 
      sourceroots{ 
       android.sourceSets.main.java.srcDirs.each{ 
        pathelement(location:it.absolutePath) 
       } 
       pathelement(location:"${project.buildDir}/source/r/${variant.dirName}") 
      } 
     } 
    } 
} 
+0

Спасибо! Моя единственная проблема сейчас - это аспект j не найти классы из проекта библиотеки, любую идею о том, как исправить это? – withoutclass

+2

У меня такая же проблема с использованием библиотек, я думал, что будет достаточно добавить проект библиотеки в iajc classpath, но кажется, что это уже есть: 'println configurations.compile.asPath' показывает путь, начинающийся с '/ home/aegar/AndroidStudioProjects/AopProject/LibTest/build/libs/LibTest.aar' в моем случае, поэтому я думаю, что проблема в том, что iajc не распознает библиотеки aar как это. – aegar

+2

@withoutclass: iajc теперь распознает мои библиотеки, я обновил ответ. Надеюсь, это сработает и для вас. – aegar

4

Хотя предыдущие ответы скрипты работает для большинства ситуации, они не охватывают некоторые проблемы использования Android с AspectJ и Gradle.

Мой тест состоял в том, чтобы создать проект библиотеки, который должен использоваться кем-либо через mavenCentral или мной как проект справочной библиотеки, и проект тестового приложения. Проект библиотеки - это тот, который имеет все аспекты, и прикладной тест пытается использовать эти аспекты. Давать это как контекст, в результате структура проекта была:

HEAD-Gradle 
---LibraryProject 
-------SomeAspects 
---TestApplication 
-------Uses-SomeAspects 

Решения я обнаружил, что делает его работы являются:

1 Для проектов библиотеки необходимо использовать

libraryVariants.all { variant -> 

вместо от

android.applicationVariants.all { variant -> 

2 - сборка с заменой на 19. + инструмент сборки s Android, так как это предлагается в одном комментарии (спасибо «Без Class»), вы должны использовать dode exploded-aar вместо dir вложенных пакетов в определении древовидной переменной. От:

def tree = fileTree(dir: "${project.buildDir}/exploded-bundles", include: '**/classes.jar') 

To:

def tree = fileTree(dir: "${project.buildDir}/exploded-aar", include: '**/classes.jar') 

3- Последняя проблема я столкнулся при создании интеграции в том, что если у вас есть проект библиотеки, аспекты, определенные на нем не были найдены на проекте ребенка , Чтобы решить эту проблему, вы должны добавить class.jar вашей пользовательской библиотеки в конфигурацию компилятора aspectJ. Вы можете достичь этого путем добавления к зависимостям:

aspects project(":YourLibraryProject") 

, и это также необходимо внести некоторые изменения в сценарии, представленной в финале этого поста.

Прямо сейчас лучший сценарий, я могу себе представить, что дает полную поддержку AspectJ использования даже проектов библиотеки является:

Для зависимостей:

configurations { 
    ajc 
    aspects 
    ajInpath 
} 

//Version of aspectj 
def aspectjVersion = '1.8.+' 
// The dependencies for this project 
dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    //Your dependencies to a custom library project 
    compile project(":YourLibraryProject") 
    aspects project(":YourLibraryProject") 
    //Aspectj dependencies 
    ajc "org.aspectj:aspectjtools:${aspectjVersion}" 
    compile "org.aspectj:aspectjrt:${aspectjVersion}" 
} 

Компилятор работает скрипт

android.applicationVariants.all { variant -> 

variant.javaCompile.doLast { 
    // Find the android.jar and add to iajc classpath 
    def androidSdk = android.adbExe.parent + "/../platforms/" + android.compileSdkVersion + "/android.jar" 

    def iajcClasspath = androidSdk + ":" + configurations.compile.asPath 
    //This line and the fordward assignations allow the aspects support in the child project from the library project 
    def customAspectsPath = configurations.aspects.asPath 
    configurations.compile.dependencies.each { dep -> 
     if(dep.hasProperty("dependencyProject")) { 
      iajcClasspath += ":" + dep.dependencyProject.buildDir + "/bundles/${variant.buildType.name}/classes.jar" 
      customAspectsPath += ":" + dep.dependencyProject.buildDir + "/bundles/${variant.buildType.name}/classes.jar" 
     } 
    } 

    // handle aar dependencies pulled in by gradle (Android support library and etc) 

    def tree = fileTree(dir: "${project.buildDir}/exploded-aar", include: '**/classes.jar') 
    tree.each { jarFile -> 
     iajcClasspath += ":" + jarFile 
    } 

    ant.taskdef(resource:"org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties", classpath: configurations.ajc.asPath) 
    ant.iajc (
      source:sourceCompatibility, 
      target:targetCompatibility, 
      destDir:"${project.buildDir}/classes/${variant.dirName}", 
      maxmem:"512m", 
      fork:"true", 
      aspectPath:customAspectsPath, 
      inpath:configurations.ajInpath.asPath, 
      sourceRootCopyFilter:"**/.svn/*,**/*.java", 
      classpath:iajcClasspath 
    ){ 
     sourceroots{ 
      android.sourceSets.main.java.srcDirs.each{ 
       pathelement(location:it.absolutePath) 
      } 
      pathelement(location:"${project.buildDir}/source/r/${variant.dirName}") 
     } 
    } 
} 
} 

Запомнить что если вы хотите запустить AspectJ в проекте library-child, вы должны также иметь этот скрипт в build.gradle библиотеки.

1

В случае использования Android Studio 0.8 или выше, кажется, что использование gradle 0.12. + Необходимо.

В градиенте 0.12. +, Взорванные аары извлекаются в папке сборки, а не в папке взорванных-aar.

Поэтому для того, чтобы справиться с AAR зависимостей, вы должны использовать этот код:

tree = fileTree(dir: "${project.buildDir}", include: '**/classes.jar') 
tree.each { jarFile -> 
    iajcClasspath += ":" + jarFile 
}