Nov 11, 2010

Adding Aspect to Android

Programming AspectJ with Android

AspectJ is the defacto choice for AOP program. So far I did not see any one trying AOP concept in Android. However, I did read one blog mentioning, it should be possible, hence I tried it.

AspectJ puts in pointcut across code and can execute advices around those pointcuts. The beautify of this is once you compile your java source, you add these pointcuts and advices to your program by injecting them in the byte code (of already generated class files).

Knowing this I knew aspectJ can be used in Android, as dex relies on .class files.

Stage 1- Let Java compile java to .class files
Stage 2- Let AspectJ compiler inject point cuts and advices to the .class files
Stage 3- Let Dex take these new class files and create .dex file.


There you should have AspectJ working for Android applications.

Case Study: Inject Tracing code to existing Android source.

Given the case that we have an existing android project, we want to trace the call graph of each thread (showing depth) and we also want to show the cumulative time for each method.

Step 1: Create an HelloWorld Android Project


























Step 2: Add some code, so we can show some call graph















Run the program and you will see this on your android emulator


















Also on the DDMS Log you will see



What we want to achieve?
We want to show the call graph for this flow. We know that the flow is this way


At the same time we would like to print the commutative time each method took





We would like to print this call graph by using AOP concepts. We would like to define pointcuts around all methods of all classes in package "com.test" and print these statements there.

Step 3: Add aspectjrt.jar to classpath of android



Step 4: Add Aspect file - Trace.aj




Following is the cut down version of the same Trace.aj file. See the inline comments



Step 5 - Compile using AspectJ

As we mentioned above we want to
1. Compile java to .class files using javac
2. Inject pointcuts and advices in .class files using aspectj compile
3. Compile these injected .class files into .dex file

For this we will use ant.

Here is the ant build.xml which I used to put aspectj compilation step between compile->dex target

Here is a snippet of my build.xml around compile and dex targets




Here is the complete build.xml for your reference

Run on command prompt or through eclipse

$> ant install

You should see following output for ant



Step 6 - Run the APK which has aspectj integrated into it (after ant install)



The log looks like as follows, just as we wanted.

12 comments:

  1. That's awesome, if i knew about this during my internship my life would have been 10 times simpler. thanks for sharing it, will try it soon.

    ReplyDelete
  2. Unfortunately, I'm getting errors:

    build.xml:330: No Project specified

    ReplyDelete
  3. Very cool, do you have to bundle the aspect.jar to your final jar file? probably right?

    ReplyDelete
  4. Nice article, do you know if it's possible to proceed post compile waving? I have an classes.dex and I'd like to change it.

    ReplyDelete
  5. Also getting errors:

    build.xml:330: No Project specified

    ReplyDelete
  6. Thanks for sharing this. I tried to post my comments here multiple times, but appears I am doing something wrong or I do not have permissions. I have posted the comments about how I got it working at this blog: http://nehal-mehta.blogspot.com/2011/06/adding-aspect-to-android.html

    ReplyDelete
  7. To the guys getting the "No Project specified" error, are you on Mac? If that's the case, 3 suggestions: 1) modify the build.properties to point to AspectJ's home (as nehalmehta says in his post) 2) check the build.xml file and check if the path to the AspectJ jars are correct (they weren't in my case, I installed it using MacPorts), 2) replace all "\" with "/" in the trace.lst file. That said now I get this pretty scary error:

    [apply]
    [apply] UNEXPECTED TOP-LEVEL EXCEPTION:
    [apply] com.android.dx.cf.code.SimException: local variable type mismatch: attempt to set or access a value of type int using a local variable of type java.lang.String. This is symptomatic of .class transformation tools that ignore local variable information.
    ...

    I can send you the complete trace if you want to take a look at it.

    ReplyDelete
  8. Hello, nice work. I've found a solution without using Ant by using AJDT plugin for Eclipse which enables also AspectJ UI guidelines and suggestions. I posted an article here: http://ikrk.wz.cz/archiv/23-how-to-use-aspectj-with-android

    Hope it helps.

    ReplyDelete
  9. Hi Adam,
    I am using the AJDT as well but I followed the HelloWorldAspectJ project demo here: http://www.eclipse.org/ajdt/demos/HelloWorldAspectJ.html. In particular what I missed was the "Convert to AspectJ" step, after doing that my project compiles again. That said: the AJDT is a bit flakey, and honestly it makes Android development even more painful (but the AJDT guys are really active and reply to bug reports quickly).

    ReplyDelete
  10. Thanks for sharing your work!
    For those who are using AJDT. I suspect that AJDT won't work if you need to weave aspects to your libraries also. At least I didn't succeeded trying that.

    ReplyDelete
  11. I should correct myself. AJDT works also. All is needed - to add libraries (or projects) which are needed to be woven to Project properties -> AspectJ build -> Inpath.

    ReplyDelete
  12. nice post........Get your Dream Home, 2bhk flat in Pune, shops information available here.

    ReplyDelete