Aspectj con la biblioteca de Android

Tengo una lib que utilizan aspectos y está disponible a través de maven, ahora estoy tratando de usar esa lib en una aplicación de Android.

Si incluyo este complemento en el archivo gradle de la aplicación, todo funciona bien, pero mi objetivo es extraer el classpath 'com.uphyca.gradle:gradle-android-aspectj-plugin:0.9.+' Y el apply plugin: 'android-aspectj' (requerido por el complemento) en el archivo gradle my.lib en lugar de declararse en mi aplicación.

¿Es eso posible?

Archivo gradle de la aplicación:

 classpath 'com.uphyca.gradle:gradle-android-aspectj-plugin:0.9.+' apply plugin: 'android-aspectj' dependencies { compile 'my.lib:example:1.0.0' } 

GOL:

Archivo gradle de la aplicación:

 dependencies { compile 'my.lib:example:1.0.0' } 

Archivo gradle my.lib:

 classpath 'com.uphyca.gradle:gradle-android-aspectj-plugin:0.9.+' apply plugin: 'android-aspectj' dependencies { compile 'org.aspectj:aspectjrt:1.7.3' } 

Yo tuve el mismo problema. Esto es todo lo que hice para resolverlo.

Proyecto raíz / principal

En su proyecto raíz, agregue las herramientas AspectJ que contienen el compilador ajc que es necesario para tejer sus clases. (También puede agregar esto al archivo build.gradle de su biblioteca, pero es mejor agregarlo aquí, ya que el complemento gradle que va a crear para acomodar su biblioteca utilizará el ajc.

 buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:1.2.3' classpath 'org.aspectj:aspectjtools:1.8.5' } 

Proyecto de biblioteca

En el archivo build.gradle de su biblioteca asegúrese de que se vea como esto similar a esto. Las adiciones principales son las declaraciones de importación en la parte superior y el código debajo de las propiedades de compilación android.

 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; } } } } 

Así que lo que sucede es cuando el proyecto está siendo compilado. El comando ajc (AspectJ weaver) compila y teje archivos AspectJ y Java y .class, produciendo archivos .class compatibles con cualquier máquina virtual Java.

Para que esto ocurra, la tarea necesita argumentos acerca de su biblioteca. Esa es la razón para crear la variable 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) ] 

A continuación, el manejador de mensajes que se crea simplemente se pasa a ajc para acumular mensajes de eventos que se producen mientras ajc está compilando / tecleando las clases. Entonces se está pasando a un registrador de proyecto que luego genera todos los errores o advertencias importantes que produjo la ajc. Por ejemplo, si un punto de corte no puede ser referenciado por un consejo, será detectado y mostrado en la consola gradle. Introduzca aquí la descripción de la imagen

Así que todo lo que se describió anteriormente se lleva a cabo aquí. Donde los args y el manejador de mensajes se están pasando a la función principal del ajc (compilador 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 Plugin

Las punterías / consejos de tu biblioteca no estaban siendo activadas porque tuviste como objetivo el módulo de la aplicación, mientras que los Aspectos se estaban tejiendo en el módulo de tu biblioteca con el com.uphyca.gradle:gradle-android-aspectj-plugin . Así que para que los Aspectos de tu biblioteca se tejan en el módulo de tu aplicación, debes crear un complemento gradle para tu proyecto. Así que lo que ha definido como su objetivo es que su pregunta no es posible, esta es la única manera que se puede hacer.

Así es como debería ser el complemento. (Plugin se hace en groovy).

Plugin's 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' } 

Entonces la clase real.

 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; } } } } } } 

Sé que esto puede parecer mucho, pero es mucho copiar y pegar porque la solución sigue siendo la misma. Si observa de cerca la clase, las mismas cosas que se están haciendo en el módulo de biblioteca se aplican ahora al módulo de la aplicación. La principal modificación que haría a esto es añadir su módulo de biblioteca a las dependencias del proyecto a través del complemento que se hace aquí.

  project.dependencies { compile 'com.letz:example-library:1.0' // TODO this should come transitively compile 'org.aspectj:aspectjrt:1.8.5' } 

Para que tu biblioteca esté disponible para tu plugin durante el desarrollo, debes asegurarte de que está siendo implementado en tu repositorio local de maven. Esto puede hacerse aplicando este complemento ( https://github.com/dcendents/android-maven-gradle-plugin ) al módulo de su biblioteca y ejecutando la tarea de gradle install .

Pasos finales

Una vez que todo esto se hace, puede aplicarlo a una aplicación de ejemplo para probar agregando esto a su archivo build.gradle

 buildscript { repositories { mavenCentral() //Only necessary when developing locally. mavenLocal() } dependencies { classpath 'com.letz:example-plugin:1.0' } } apply plugin: 'example-plugin' 

Una vez hecho esto, tu biblioteca estará disponible para la aplicación porque se agrega al proyecto una vez que se ha aplicado el complemento.

Si las cosas todavía son confusas, estás en buena suerte porque el proyecto que implemente esta solución está en Github para que puedas bifurcarlo, copiar el proyecto del complemento y hacer los cambios necesarios.

El proyecto se llama Flender y se utiliza para anotar los métodos que requieren la comprobación de conectividad. Aquí está el enlace https://github.com/jd-alexander/flender

Espero que esta respuesta ayude.

  • MediaPlayer seekTo () no actualiza SurfaceView
  • FindViewById en DialogFragment - NullPointerException
  • LocationClient getLastLocation () devolver null
  • "ItemizedOverlay" no se puede resolver con un tipo
  • Tipo de retorno flexible
  • Android: crea un servicio que se ejecuta una vez al día
  • Square Retrofit Client: ¿Cómo activar / desactivar followRedirects? Cómo interceptar URL de redireccionamiento?
  • ¿Puedo autenticarme con AWS Cognito desde Java simple?
  • Cómo obtener un valor aleatorio de una matriz de cadenas en android?
  • ¿Es esta una buena técnica (Uso de titular de datos) para eliminar la clase anónima, para reducir el riesgo de pérdida de memoria
  • OpenCV color-valor de un píxel usando mat.get () devuelve a veces null
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.