Aspect Oriented Programming in Android

Having heard about aspect-oriented programming, I, as an Android developer, immediately thought that it was unlikely to work on Android, however, I decided to give it a try. I was very surprised when after 5 minutes an application using AspectJ successfully worked on the phone.

I won’t convince of the need to use aspects in Android and give examples of “uses cases”, I’ll just give an example of how to add the possibility of using aspects to my application. What are aspects and why use them is well described, for example, on the wiki .

As an IDE for development, I switched to Android Studio a long time ago, and therefore I use gradle as a build system. For her, I will give an example of configuration.

The entire AspectJ connection process consists of the following steps:

  1. We connect the plug-in for assembly:
    In the section of buildscriptthe build script of your project, add to the dependenciesline:
    classpath 'com.uphyca.gradle:gradle-android-aspectj-plugin:0.9.+'

  2. In build.gradlethe application module add:
    apply plugin: "android-aspectj"

  3. ... and depending on the module, add:
    dependencies {
        compile 'org.aspectj:aspectjrt:1.8.+'
    }
    

  4. We write the aspect itself.
    Aspects can be written using special syntax in files with the as extension, or using java + a number of annotations. Since Android Studio does not include the AspectJ plugin, I preferred the second option (For owners of the Ultimate version of IDEA, both options are available):
    
    @Aspect
    public class MainActivityAspect {
        private static final String TAG = "helloaspectj";
        @Pointcut("execution(* ru.hoticecream.helloaspectj.ui.MainActivity.onCreate(..))")
        public void onCreateMethod(){}
        @Before("onCreateMethod()")
        public void doBeforeOnCreate(JoinPoint joinPoint) {
            Log.i(TAG, "AspectJ was here");
        }
    }
    

    This aspect is embedded before the method call MainActivity.onCreate, displaying the corresponding message in the log.


Now, by launching the application and opening MainActivity, we will see in the log:
... I/helloaspectj﹕ AspectJ was here

I will give another example of the use of the aspect.
To do this, add a method to MainActivity that sets a message to a specific text field:

    private TextView mGreetingText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mGreetingText = (TextView) findViewById(R.id.greeting_message);
        setGreetingMessage("Hello Android");
    }
    private void setGreetingMessage(String message) {
        mGreetingText.setText(message);
    }

As you can see, the field takes the value “Hello Android”, starting the application you can see this;)

Now we add all the following methods to the same aspect class:

    @Pointcut("execution(* ru.hoticecream.helloaspectj.ui.MainActivity.setGreetingMessage(..))")
    public void setGreetingMessageMethod(){}
    @Around("setGreetingMessageMethod()")
    public void makeNasty(final ProceedingJoinPoint pjp)
            throws Throwable {
        Log.d(TAG, pjp.getSignature().toLongString());
        pjp.proceed(new Object[] { "Hello AspectJ" });
    }

Now, this aspect is still looking for a method setGreetingMessageand replaces its call with the contents of the method makeNasty, using the annotation for this. @Around

Running the application, we will already see “Hello AspectJ”. At the same time, MainActivity.javawe did not change.

That's all. I hope the article was useful to you.

Finally, a couple of links:

Also popular now: