在Google IO中,宣布新的构建系统gradle将取代ant。 我的项目是使用aspectj,我想在我的项目中使用它。 我无法找出一些变量来使它工作。我没有找到android。*输出类路径。有人可以帮忙吗?
这是我当前的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)
}
}
}
}
这是一个非常有效的旧ant代码: 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 :(得分:15)
我也想在gradle和Android Studio中使用aspectj,我终于让它工作了,但我仍然有一些手写的路径,我想用更通用的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}
,根据当前的构建配置,它将被“debug”或“release”替换。
编译Android特定类需要将android.jar添加到类路径中,并且需要使用行pathelement(location:"${project.buildDir}/source/r/${variant.dirName}")
来使用自动生成的R.java文件中的类。
编辑:对构建iajcClasspath的项目依赖项的迭代允许您使用库项目中的类。 configurations.compile.asPath
已经包含对你的apklib(aar文件)的引用,它实际上是一个包含jar和库资源的zip。 Iajc不识别这些文件,但是在build目录下有一个包含classes.jar的包目录。我在其中使用了一个带有“release”硬编码的相对路径,因为在我的情况下,库与主项目有不同的变体,所以我不能在这里使用${variant.dirName}
。
这是完整的build.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}")
}
}
}
}
答案 1 :(得分: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
答案 2 :(得分:4)
虽然以前的答案脚本适用于大多数情况,但它们并未涵盖使用Android与AspectJ和Gradle的一些问题。
我的测试是创建一个库项目,任何人都可以通过mavenCentral或我作为参考库项目和测试应用程序项目使用它。图书馆项目具有所有方面,应用程序测试试图使用这些方面。 将此作为上下文,生成的项目结构为:
HEAD-Gradle
---LibraryProject
-------SomeAspects
---TestApplication
-------Uses-SomeAspects
我发现使其有效的解决方案是:
1-对于图书馆项目,您必须使用
libraryVariants.all { variant ->
而不是
android.applicationVariants.all { variant ->
2-构建目录已更改为19. + Android构建工具,因此在一条评论中建议(感谢“WithoutClass”),您必须使用explosion-aar目录而不是explosion-bundles目录树变量定义。 从:
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上也有此脚本。
答案 3 :(得分:1)
在使用Android Studio 0.8或更高版本的情况下,似乎需要使用gradle 0.12。+。
在gradle 0.12。+中,爆炸aar在build文件夹中提取,而不是在explosion-aar文件夹中提取。
因此,为了处理aar依赖项,您必须使用以下代码:
tree = fileTree(dir: "${project.buildDir}", include: '**/classes.jar')
tree.each { jarFile ->
iajcClasspath += ":" + jarFile
}
答案 4 :(得分:1)
另一种更简单的设置方法是使用更方便维护的android aspectj插件。 https://github.com/uPhyca/gradle-android-aspectj-plugin