У меня была такая же проблема. Это все, что я сделал, чтобы решить эту проблему.
Root/Main Project
В корневом проекте добавить инструменты AspectJ, которые содержат АЕК компилятор, который необходим для ткачества классы. (Вы также можете добавить это в файл build.gradle вашей библиотеки, но это лучше, чтобы добавить его здесь как Gradle плагин, который вы будете создавать для размещения вашей библиотеки будет использовать AJC.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.3'
classpath 'org.aspectj:aspectjtools:1.8.5'
}
проекта Библиотека
в файле build.gradle вашей библиотеки убедитесь, что это выглядит примерно так. Основные дополнения являются операторы импорта в верхнем и код под андроидом свойств сборки.
import com.android.build.gradle.LibraryPlugin
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
apply plugin: 'com.android.library'
dependencies {
compile 'org.aspectj:aspectjrt:1.8.5'
}
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
android.libraryVariants.all { variant ->
LibraryPlugin plugin = project.plugins.getPlugin(LibraryPlugin)
JavaCompile javaCompile = variant.javaCompile
javaCompile.doLast {
String[] args = [
"-showWeaveInfo",
"-1.5",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", android.bootClasspath.join(File.pathSeparator)
]
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler)
def log = project.logger
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break;
case IMessage.WARNING:
case IMessage.INFO:
log.info message.message, message.thrown
break;
case IMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
Итак, что происходит, когда проект компилируется, команда ajc (aspectJ's weaver) компилирует и вставляет файлы AspectJ и Java source и .class, создавая файлы .class, совместимые с любой виртуальной машиной Java.
Для этого задача требует аргументов в отношении вашей библиотеки. В этом причина создания переменной args.
String[] args = [
"-showWeaveInfo",
"-1.5",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", android.bootClasspath.join(File.pathSeparator)
]
Тогда обработчик сообщений, который создается просто передается в АЕК аккумулировать сообщения о событиях, которые происходят в то время как AJC компилирует/сотка классы. Затем он передается в регистратор проектов, который затем выводит любые важные ошибки или предупреждения, которые создаются ajc. Например, если pointcut не может ссылаться на совет, он будет обнаружен и показан в консоли gradle.
Так что все, что описано выше, в основном происходит прямо здесь. Где args и обработчик сообщений передаются на главную функцию ajc (компилятор AspectJ).
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler)
def log = project.logger
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
Gradle Плагин
точка срезы/советы вашей библиотеки не были срабатывает, потому что вы целились модуль приложения в то время как аспекты были вплетены только в модуль вашей библиотеки с com.uphyca.gradle:gradle-android-aspectj-plugin
AspectJ плагина. Поэтому для того, чтобы Аспекты вашей библиотеки были вплетены в ваш модуль App, вы должны создать плагин для вашего проекта. Итак, что вы определили как свою цель, ваш вопрос невозможен, это единственный способ сделать это.
Вот как должен выглядеть плагин. (Плагин выполнен в паре).
build.gradle
apply plugin: 'groovy'
targetCompatibility = JavaVersion.VERSION_1_7
sourceCompatibility = JavaVersion.VERSION_1_7
dependencies {
compile gradleApi()
compile localGroovy()
compile 'com.android.tools.build:gradle:1.1.0-rc3'
compile 'org.aspectj:aspectjtools:1.8.5'
compile 'org.aspectj:aspectjrt:1.8.5'
}
Тогда фактический класс плагина.
import com.android.build.gradle.AppPlugin
import com.android.build.gradle.LibraryPlugin
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
import org.gradle.api.Plugin
import org.gradle.api.Project
public class YourPlugin implements Plugin<Project> {
@Override void apply(Project project) {
def hasApp = project.plugins.withType(AppPlugin)
def hasLib = project.plugins.withType(LibraryPlugin)
if (!hasApp && !hasLib) {
throw new IllegalStateException("'android' or 'android-library' plugin required.")
}
final def log = project.logger
final def variants
if (hasApp) {
variants = project.android.applicationVariants
} else {
variants = project.android.libraryVariants
}
project.dependencies {
compile 'com.name:example:1.0'
// TODO this should come transitively
compile 'org.aspectj:aspectjrt:1.8.5'
}
variants.all { variant ->
variant.dex.doFirst {
String[] args = [
"-showWeaveInfo",
"-1.5",
"-inpath", javaCompile.destinationDir.toString(),
"-aspectpath", javaCompile.classpath.asPath,
"-d", javaCompile.destinationDir.toString(),
"-classpath", javaCompile.classpath.asPath,
"-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)
]
log.debug "ajc args: " + Arrays.toString(args)
MessageHandler handler = new MessageHandler(true);
new Main().run(args, handler);
for (IMessage message : handler.getMessages(null, true)) {
switch (message.getKind()) {
case IMessage.ABORT:
case IMessage.ERROR:
case IMessage.FAIL:
log.error message.message, message.thrown
break;
case IMessage.WARNING:
log.warn message.message, message.thrown
break;
case IMessage.INFO:
log.info message.message, message.thrown
break;
case IMessage.DEBUG:
log.debug message.message, message.thrown
break;
}
}
}
}
}
}
Я знаю, это может показаться много, но это много копирования и вставки, потому что решение остается тем же самым. Если вы внимательно посмотрите на класс, то те же самые вещи, которые выполняются в вашем библиотечном модуле, теперь применяются к модулю вашего приложения. Основная модификация, которую вы сделали бы с этим: добавьте свой библиотечный модуль в зависимости от проекта через плагин, который здесь делается.
project.dependencies {
compile 'com.letz:example-library:1.0'
// TODO this should come transitively
compile 'org.aspectj:aspectjrt:1.8.5'
}
Для вашей библиотеки должны быть доступны для вашего плагина при разработке вы должны убедиться, что она развертывается в локальный репозиторий Maven. Это можно сделать, применив этот плагин (https://github.com/dcendents/android-maven-gradle-plugin) к вашему библиотечному модулю и запустив задачу gradle install
.
Заключительные шаги
После того, как все это будет сделано, то вы можете применить его к пример приложения для тестирования, добавив в него это build.gradle файл
buildscript {
repositories {
mavenCentral()
//Only necessary when developing locally.
mavenLocal()
}
dependencies {
classpath 'com.letz:example-plugin:1.0'
}
}
apply plugin: 'example-plugin'
После того, как это сделано в вашей библиотеке будет доступно для приложения, потому что он добавляется в проект после применения плагина.
Если все еще запутано, вам очень повезло, потому что проект, который я реализовал это решение, находится на Github, поэтому вы можете его разветвить, скопировать проект плагина и внести необходимые изменения.
Проект называется Flender и используется для аннотирования методов, требующих проверки связи. Вот ссылка https://github.com/jd-alexander/flender
Надеюсь, что этот ответ поможет.