android aspectj,java - Aspectj with android library - Stack Overflow

I had the same problem. This is all I did to solve it.

Root/Main Project

In your root project add the AspectJ tools that contains the ajc compiler that is necessary for weaving your classes. ( You can also add this to your library's build.gradle file but it's better to add it here as the gradle plugin that you will be creating to accommodate your library will be using the ajc.

buildscript {

repositories {

jcenter()

}

dependencies {

classpath 'com.android.tools.build:gradle:1.2.3'

classpath 'org.aspectj:aspectjtools:1.8.5'

}

Library Project

In your library's build.gradle file ensure that it looks like this similar to this. The main additions are the import statements at the top and the code beneath the android build properties.

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;

}

}

}

}

So what's happening is when the project is being compiled the ajc(AspectJ's weaver) command compiles and weaves AspectJ and Java source and .class files, producing .class files compliant with any Java VM.

For this to take place the task needs arguments about your library. That's the reason for creating the args variable.

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)

]

Then the message handler that's created is simply being passed to ajc to accumulate messages of events that are taking place while ajc is compiling/weaving the classes. Then it's being passed to a project logger that then outputs any important errors or warnings that the ajc produced. For example if a pointcut can't be referenced by an advice it will be detected and shown in the gradle console.

aJF0s.png

So all of what was describe above is basically taking place right here. Where the args and message handler are being passed to the Main function of the ajc(AspectJ compiler).

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

The pointcuts/advices of your library weren't being triggered because you were targeting the app module while Aspects were only being woven into your library's module with the com.uphyca.gradle:gradle-android-aspectj-plugin AspectJ plugin. So in order for the Aspects of your library to be woven into your App's module you have to create a gradle plugin for your project. So what you have defined as your goal is your question is not possible, this is the only way it can be done.

This is how the plugin should look. (Plugin is done in 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'

}

Then the actual class.

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 {

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

}

}

}

}

}

}

I know this might seem like a lot but it's alot of copy and pasting because the solution remains the same. If you look closely at the class the same things being done in your library module is now being applied to your app's module.

The main modification you would do to this is add your library module to the project's dependencies via the plugin that's done here.

project.dependencies {

compile 'com.letz:example-library:1.0'

// TODO this should come transitively

compile 'org.aspectj:aspectjrt:1.8.5'

}

For your library to be available to your plugin while developing you have to ensure that it's being deployed to your local maven repository. This can be done by applying this plugin(https://github.com/dcendents/android-maven-gradle-plugin) to your library module and running the gradle install task.

Final Steps

Once all of that is done you can then apply it to a sample app for testing by adding this to it's build.gradle file

buildscript {

repositories {

mavenCentral()

//Only necessary when developing locally.

mavenLocal()

}

dependencies {

classpath 'com.letz:example-plugin:1.0'

}

}

apply plugin: 'example-plugin'

Once that's done your library will be available to the app because it's being added to the project once the plugin has been applied.

If things are still confusing you are in good luck because the project I implemented this solution is on Github so you can fork it, copy the plugin's project and make the necessary changes.

The project is called Flender and it's used to annotate methods that require connectivity checking. Here's the link https://github.com/jd-alexander/flender

Hope this answer helps.

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值