2013-06-21 32 views
17

在Google IO中,新的build system gradle被宣佈替換ant。 我的項目使用的是aspectj,我想在我的項目中使用它。 我找不出一些變量來使它工作。我沒有找到android。*輸出類路徑。任何人都可以幫忙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

編輯:

更新根據的的build.gradle第一個答案。然而,我iajc似乎並沒有認出所有圖書館,並抱怨圖書館沒有找到類。

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]    

編輯: 這最後的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嗎?我指向的地方是「/ home/aegar/android-sdk/platforms」,我只有android-18。 – aegar

+0

這是AAR依賴性問題。 AAR不能用作罐子。你處理了dependencyProject,但是,如果你指定了編譯'com.android.support:appcompat-v7:18.0.0',classes.jar是在分解包中,這個目錄中的所有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) 

對於完整的示例,請參閱AnyMemo項目在這裏的build.gradle: https://code.google.com/p/anymemo/source/browse/build.gradle?spec=svnf85aaa4b2d78c62876d0e1f6c3e28252bf03f820&r=f85aaa4b2d78c62876d0e1f6c3e28252bf03f820

+0

注意:使用工具19我認爲他們可能已經改變了位置。我需要使用'exploded-aar'而不是上面例子中的'exploded-bundles'。 – withoutclass

+0

withoutclass,是的他們改了名字。 https://code.google.com/p/anymemo/source/browse/build.gradle?spec=svnf85aaa4b2d78c62876d0e1f6c3e28252bf03f820&r=f85aaa4b2d78c62876d0e1f6c3e28252bf03f820有變化。 – Liberty

+0

謝謝!我錯過了這篇文章,並在我放棄並在這裏看到之前與aegar答覆鬥爭。這個答案需要更多upvotes。 – dieend

15

我也想用AspectJ與gradle這個和Android工作室,我終於得到它的工作,但我仍然有一些手寫的路徑,我想用更通用的gradle選項來替換。

編輯:我用基於gradle的替代方案替換了每個硬編碼的絕對路徑,因此此解決方案不再依賴給定的平臺或用戶名。但是,它仍然使用相對路徑,這些路徑可能會從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},將被替換根據當前的構建配置,通過「調試」或「發佈」。

需要將android.jar添加到類路徑才能編譯Android特定的類,並且pathelement(location:"${project.buildDir}/source/r/${variant.dirName}")行需要使用自動生成的R.java文件中的類。

編輯:通過構建iajcClasspath的項目依賴關係的迭代,您可以使用庫項目中的類。 configurations.compile.asPath已經包含對你的apklib(aar文件)的引用,它實際上是一個包含jar和庫資源的zip文件。 Iajc無法識別這些文件,但在構建目錄下有一個包含用於庫的classes.jar的包目錄。我使用硬編碼的「釋放」相對路徑,因爲該庫與我的情況下的主項目有不同的變體,所以在這裏我不能使用${variant.dirName}

這是完整的版本。gradle文件:

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

謝謝!我現在唯一的問題是aspectj沒有從圖書館項目中找到類,有關如何解決這個問題的任何想法? – 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

雖然以前的答案腳本適用於大多數的這些情況並未涵蓋在AspectJ和Gradle中使用Android的一些問題。

我的測試是創建一個庫項目,任何人都應該通過mavenCentral或我作爲參考庫項目和測試應用程序項目來使用它。圖書館項目是具有所有方面的應用程序測試試圖使用這些方面的項目。 給予這是一個情況下,得到的項目結構爲:

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

的解決方案,我發現,使工作有:

1-對於庫項目必須使用

libraryVariants.all { variant -> 

代替

android.applicationVariants.all { variant -> 

2-構建目錄更改爲19. +構建工具因爲它是在一個註釋中提到的(感謝「WithoutClass」),所以你必須在樹變量定義中使用爆炸式的目錄而不是爆炸式的束目錄。 來源:

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

要:

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

3-使得整合是,如果你有一個庫項目,它定義方面進行了不上孩子的項目發現,當我面對的最後一個問題。爲了解決這個問題,你必須將你的自定義庫的classes.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,則必須在庫的build.gradle上也有此腳本。

1

在使用Android Studio 0.8或更高版本的情況下,似乎需要使用Gradle 0.12。+。

在gradle 0.12。+中,展開的aar在構建文件夾中提取,而不是在展開的aar文件夾中。

因此,爲了處理AAR的依賴,則必須使用此代碼:

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