AspectJ Gradle


Source link: https://github.com/Archinamon/GradleAspectJ-Android

GradleAspectJ-Android

A Gradle plugin which enables AspectJ for Android builds. Supports writing code with AspectJ-lang in .aj files and in java-annotation style. Full support of Android product flavors and build types. Support Kotlin, Groovy, Scala and any other languages that compiles into java bytecode.

Actual version: com.archinamon:android-gradle-aspectj:3.2.0.
Friendly with jRebel for Android!

This plugin is completely friendly with APT (Android Annotation Processing Tools) and Retrolambda project (but Java 8 not supported in .aj files). AndroidAnnotations, Dagger are also supported and works fine.

This plugin has many ideas from the others similar projects, but no one of them grants full pack of features like this one. Nowdays it has been completely re-written using Transform API.

Key features

Augments Java, Kotlin, Groovy bytecode simultaneously!
Works with background mechanics of jvm-based languages out-of-box!
How to teach Android Studio to understand the AspectJ!
May not work properly for AS 3.0 :(

It is easy to isolate your code with aspect classes, that will be simply injected via cross-point functions, named advices, into your core application. The main idea is — code less, do more!

AspectJ-Gradle plugin provides supply of all known JVM-based languages, such as Groovy, Kotlin, etc. That means you can easily write cool stuff which may be inject into any JVM language, not only Java itself! :)

To start from you may look at my example project. And also you may find useful to look at reference manual of AspectJ language and simple code snipets. In case aspectj-native not supported by Android Studio (even with IDE-plugin it's using is complicated), you may write a java-classes with aspectj annotations.

Two simple rules you may consider when writing aspect classes.

  • Do not write aspects outside the src/$flavor/aspectj source set! These aj-classes will be excluded from java compiler.
  • Do not try to access aspect classes from java/kotlin/etc. In case java compiler doesn't know anything about aspectj, it will lead to compile errors on javac step.

These rules affects only in case you're writing in native aj-syntax. You may write aspects in java-annotation style and being free from these limitations.

Usage

First add a maven repo link into your repositories block of module build file:

mavenCentral()

Don't forget to add mavenCentral() due to some dependencies inside AspectJ-gradle module.

Add the plugin to your buildscript's dependencies section:

classpath 'com.archinamon:android-gradle-aspectj:3.2.0'

Apply the aspectj plugin:

apply plugin: 'com.archinamon.aspectj'

Now you can write aspects using annotation style or native (even without IntelliJ IDEA Ultimate edition). Let's write simple Application advice:

import android.app.Application; import android.app.NotificationManager; import android.content.Context; import android.support.v4.app.NotificationCompat;  aspect AppStartNotifier {

pointcut postInit(): within(Application+) && execution(* Application+.onCreate());

after() returning: postInit() {

Application app = (Application) thisJoinPoint.getTarget();

NotificationManager nmng = (NotificationManager) app.getSystemService(Context.NOTIFICATION_SERVICE);

nmng.notify(9999, new NotificationCompat.Builder(app)

 .setTicker("Hello AspectJ")

 .setContentTitle("Notification from aspectJ")

 .setContentText("privileged aspect AppAdvice")

 .setSmallIcon(R.drawable.ic_launcher)

 .build());

  
}
 
}

Tune extension

aspectj {

  ajc '1.8.12' // default value

/* @see Ext plugin config **/
  includeAllJars false // default value
  includeJar 'design', 'support-v4', 'dagger' // default is empty
  excludeJar 'support-v7', 'joda' // default is empty
  extendClasspath true // default value

includeAspectsFromJar 'my-aj-logger-lib', 'any-other-libs-with-aspects'  // default is empty
  ajcArgs << '-referenceInfo' << '-warn:deprecation'

weaveInfo true // default value
  debugInfo false // default value
  addSerialVersionUID false // default value
  noInlineAround false // default value
  ignoreErrors false // default value

 breakOnError true // default value
  experimental false // default value
  buildTimeLog true // default value

transformLogFile 'ajc-transform.log' // default value
  compilationLogFile 'ajc-compile.log' // default value 
}

Note that you may not include all these options!

All the extension parameters are have default values (all of them are described above, except of includeJar/Aspects/ajcArgs options). So no need to define them manually.

  • ajc Allows to define the aspectj runtime jar version manually (1.8.12 current)

  • extendClasspath Explicitly controls whether plugin should mutate the classpath with aspectj-runtime itself

  • includeAllJars Explicitly include all available jar-files into -inpath to proceed by AJ-compiler

  • includeJar Name filter to include any jar/aar which name or path satisfies the filter

  • excludeJar Name filter to exclude any jar/aar which name or path satisfies the filter

  • includeAspectsFromJar Name filter to include any jar/aar with compiled binary aspects you wanna affect your project

  • ajcExtraArgs Additional parameters for aspectj compiler

  • weaveInfo Enables printing info messages from Aj compiler

  • debugInfo Adds special debug info in aspect's bytecode

  • addSerialVersionUID Adds serialVersionUID field for Serializable-implemented aspect classes

  • noInlineAround Strict ajc to inline around advice's body into the target methods

  • ignoreErrors Prevent compiler from aborting if errors occurrs during processing the sources

  • breakOnError Allows to continue project building when ajc fails or throws any errors

  • experimental Enables experimental ajc options: -XhasMember and -Xjoinpoints:synchronization,arrayconstruction. More details in issue #18

  • buildTimeLog Appends a BuildTimeListener to current module that prints time spent for every task in build flow, granularity in millis

  • transformLogFile Defines name for the log file where all Aj compiler info writes to, new separated for Transformer

  • compilationLogFile Defines name for the log file where all Aj compiler info writes to, new separated for CompileTask

Extended plugin config

apply plugin: 'com.archinamon.aspectj-ext'

Ext config:

  • allows usage of includeJar and includeAllJars parameters, with workaround to avoid Multiple dex files exception
  • supports multiDex
  • supports Instrumented tests

Currently it has some limitations:

  • InstantRun must be switched off (Plugin detects IR status and fails build if IR will be found).

Provider plugin config

apply plugin: 'com.archinamon.aspectj-provides'

Plugin-provider may be useful for that cases when you need to extract aspect-sources into separate module and include it on demand to that modules where you only need it. Therefor this behavior will save you build-time due to bypassing aspectj-transformers in provide-only modules.

You ain't limited to describe as much provider-modules as you need and then include them using includeAspectsFromJar parameter in the module which code or dependencies you may want to augment.

With example project you could learn how to write such provider-module.

Working tests

apply plugin: 'com.archinamon.aspectj-test'

Test scope configuration inherits aspectj-ext behavior with strictly excluding compile and transform tasks from non-test build variant. In other words only instrumentation androidTest will work with this sub-plugin. In case unit tests doesn't really have any specials (excluding source/target code version base) so aspectj-test scope won't affect unitTest variants.

ProGuard

Correct tuning will depends on your own usage of aspect classes. So if you declares inter-type injections you'll have to predict side-effects and define your annotations/interfaces which you inject into java classes/methods/etc. in proguard config.

Basic rules you'll need to declare for your project:

-adaptclassstrings -keepattributes InnerClasses, EnclosingMethod, Signature, *Annotation*  -keepnames @org.aspectj.lang.annotation.Aspect class * {

  ajc* <methods>; 
}
 

If you will face problems with lambda factories, you may need to explicitely suppress them. That could happen not in aspect classes but in any arbitrary java-class if you're using Retrolambda. So concrete rule is:

-keep class *$Lambda* {
 <methods>; 
}
 -keepclassmembernames public class * {

  *** lambda*(...);
 
}
 

Changelog

3.2.0 -- Gradle 3.0.0 support

  • added support of stable gradle plugin 3.0.0;
  • updated internal ajc and provided aj runtime library versions to the latest 1.8.12;

3.1.1 -- Useful improvements

  • added an extension trigger to append BuildTime logger for current module;
  • back from grave — added exclude-filter for aspectj-ext plugin;

3.1.0 -- Provider

  • implemented provides plugin split to effectively extract aspects to external/sub modules;
  • small code improvements and cleanups;

3.0.3 -- Minor fixes

  • fixed aar detecting mechanism;
  • registered plugin in mavenCentral!

3.0.0 -- Grand refactoring in Kotlin

  • all groovy classes was obsolete;
  • new code-base in Kotlin 1.1.1 stable;

2.4.3 -- Hot-fixed two-step compilation

  • compiled in first step aspect classes have not been copied to final output;

2.4.2 -- Hot-fix

  • fixed missed variable;
  • fixed imports;

2.4.0 -- Added aspectj-ext plugin

  • includeJar parameter now able to read aar's manifest file to exactly detect required library;
  • com.archinamon.aspectj-ext plugin added to properly weave inpath jars, in this mode InstantRun doesn't allowed;
  • small fixes and package/name refactoring;

2.3.1 -- New two-step build mechanic

  • renamed extension parameter: ajcExtraArgs -> ajcArgs;
  • split parameter: logFileName -> [transformLogFile, compilationLogFile];
  • added separate compile task to build all sources under /aspectj folder;
  • aj-transformer now looks into /build/aspectj/$variantName folder for aspects class';
  • updated ajc-version to 1.8.10;
  • fixed issue with missing error printing to Messages when failing;
  • added inpath/aspectpath clearance before emitting transform inputs (by @philippkumar);

2.3.0 -- Major fixes

  • InstantRun support;
  • fails androidTest hot launch;
  • ZipException within augmenting third party libraries via AspectJ;
  • more clear logging and errors emitting;

2.2.2 -- Improvements

  • fixed build config namings;
  • re-designed work with log file and errors handling;
  • pretty formatting ajc arguments for build stdout;
  • implemented handling custom ajc arguments via build.gradle config;

2.2.1 -- Hot-fix

  • fixed illegal 'return' statement;
  • change included in updated 2.2.0 artifacts;

2.2.0 -- Ajc fixes and improvements

  • fixed problem with -aspectPath building project with multidex;
  • fixed scope problems with Transform API;
  • removed Java 8 support;
  • implemented clear and easy way to attach compiled aspects via jar/aar;
  • implemented more easy way to weave by aspects any library (jar/aar);
  • implemented breaking build on errors occurring to prevent runtime issues;
  • implemented ajc experimental features: -XhasMember and -Xjoinpoints:synchronization,arrayconstruction;
  • implemented more logic way to detect the plugin placement in build file to support retrolambda correctly;
  • code cleanups and improvements;

2.1.0 -- Transform api fix

  • finally fixed errors with multidex;
  • fixed jar merge errors;
  • fixed errors with new gradle plugin;
  • fixed Java 8 support;
  • fixed Retrolambda compatibility;

2.0.4 -- Small fix

  • fixed error with mandatory default aj-directory;

2.0.3 -- Gradle instant run

  • merged pull request with the latest gradle plugin update;
  • fixed errors after update;

2.0.2 -- Fixed filters

  • problem with empty filters now fixed;

2.0.1 -- Hotfix :)

  • proper scan of productFlavors and buildTypes folders for aj source sets;
  • more complex selecting aj sources to compile;
  • more precise work with jars;
  • changed jar filter policy;
  • optimized weave flags;

2.0.0 -- Brand new mechanics

  • full refactor on Transform API;
  • added new options to aspectj-extension;

1.3.3 -- Rt qualifier

  • added external runtime version qualifier;

1.3.2 -- One more fix

  • now correctly sets destinationDir;

1.3.1 -- Hot-fixes

  • changed module name from AspectJ-gradle to android-gradle-aspectj;
  • fixed couple of problems with test flavours processing;
  • added experimental option: weaveTests;
  • added finally post-compile processing for tests;

1.3.0 -- Merging binary processing and tests

  • enables binary processing for test flavours;
  • properly aspectpath and after-compile source processing for test flavours;
  • corresponding sources processing between application modules;

1.2.1 -- Hot-fix of Gradle DSL

  • removed unnecessary parameters from aspectj-extension class;
  • fixed gradle dsl-model;

1.2.0 -- Binary weaving

  • plugin now supports processing .class files;
  • supporting jvm languages — Kotlin, Groovy, Scala;
  • updated internal aj-tools and aj runtime to the newest 1.8.9;

1.1.4 -- Experimenting with binary weaving

  • implementing processing aars/jars;
  • added excluding of aj-source folders to avoid aspects re-compiling;

1.1.2 -- Gradle Instant-run

  • now supports gradle-2.0.0-beta plugin and friendly with slicer task;
  • fixed errors within collecting source folders;
  • fixed mixing buildTypes source sets;

1.1.1 -- Updating kernel

  • AspectJ-runtime module has been updated to the newest 1.8.8 version;
  • fixed plugin test;

1.1.0 -- Refactoring

  • includes all previous progress;
  • updated aspectjtools and aspectjrt to 1.8.7 version;
  • now has extension configuration;
  • all logging moved to the separate file in app/build/ajc_details.log;
  • logging, log file name, error ignoring now could be tuned within the extension;
  • more complex and correct way to detect and inject source sets for flavors, buildTypes, etc;

1.0.17 -- Cleanup

  • !!IMPORTANT!! now corectly supports automatically indexing and attaching aspectj sources within any buildTypes and flavors;
  • workspace code refactored;
  • removed unnecessary logging calls;
  • optimized ajc logging to provide more info about ongoing compilation;

1.0.16 -- New plugin routes

  • migrating from corp to personal routes within plugin name, classpath;

1.0.15 -- Full flavor support

  • added full support of buld variants within flavors and dimensions;
  • added custom source root folder -- e.g. src/main/aspectj/path.to.package.Aspect.aj;

1.0.9 -- Basic flavors support

  • added basic support of additional build varians and flavors;
  • trying to add incremental build //was removed due to current implementation of ajc-task;

1.0 -- Initial release

  • configured properly compile-order for gradle-Retrolambda plugin;
  • added roots for preprocessing generated files (needed to support Dagger, etc.);
  • added MultiDex support;

Known limitations

  • You can't speak with sources in aspectj folder due to excluding it from java compiler;
  • Doesn't support gradle-experimental plugin;

All these limits are fighting on and I'll be glad to introduce new build as soon as I solve these problems.

License

Copyright 2015 Eduard "Archinamon" Matsukov.  Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License. You may obtain a copy of the License at
  http://www.apache.org/licenses/LICENSE-2.0  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 

Resources

Small, but beautiful MaterialImageView.

Open Location Codes are short generated codes, that can be used like street addresses, for places where street addresses don't exist.

Clockwise is a watch face framework for Android Wear developed by ustwo. It extends the Android Wear Watch Face API and provides base classes and helpers for quickly and correctly developing watch faces. This includes properly handling the various modes of operation, hardware constraints, changes in date/time/time zone, access to data, and performance considerations.

Gradle plugin to upload your APK and app details to the Google Play Store. Needs the com.android.application plugin applied. Supports the Android Application Plugin as of version 1.0.0.

Android Library to make TimePicker View.

SwipeBack is a android library that can finish a activity by using gesture.

Topics


2D Engines   3D Engines   9-Patch   Action Bars   Activities   ADB   Advertisements   Analytics   Animations   ANR   AOP   API   APK   APT   Architecture   Audio   Autocomplete   Background Processing   Backward Compatibility   Badges   Bar Codes   Benchmarking   Bitmaps   Bluetooth   Blur Effects   Bread Crumbs   BRMS   Browser Extensions   Build Systems   Bundles   Buttons   Caching   Camera   Canvas   Cards   Carousels   Changelog   Checkboxes   Cloud Storages   Color Analysis   Color Pickers   Colors   Comet/Push   Compass Sensors   Conferences   Content Providers   Continuous Integration   Crash Reports   Credit Cards   Credits   CSV   Curl/Flip   Data Binding   Data Generators   Data Structures   Database   Database Browsers   Date &   Debugging   Decompilers   Deep Links   Dependency Injections   Design   Design Patterns   Dex   Dialogs   Distributed Computing   Distribution Platforms   Download Managers   Drawables   Emoji   Emulators   EPUB   Equalizers &   Event Buses   Exception Handling   Face Recognition   Feedback &   File System   File/Directory   Fingerprint   Floating Action   Fonts   Forms   Fragments   FRP   FSM   Functional Programming   Gamepads   Games   Geocaching   Gestures   GIF   Glow Pad   Gradle Plugins   Graphics   Grid Views   Highlighting   HTML   HTTP Mocking   Icons   IDE   IDE Plugins   Image Croppers   Image Loaders   Image Pickers   Image Processing   Image Views   Instrumentation   Intents   Job Schedulers   JSON   Keyboard   Kotlin   Layouts   Library Demos   List View   List Views   Localization   Location   Lock Patterns   Logcat   Logging   Mails   Maps   Markdown   Mathematics   Maven Plugins   MBaaS   Media   Menus   Messaging   MIME   Mobile Web   Native Image   Navigation   NDK   Networking   NFC   NoSQL   Number Pickers   OAuth   Object Mocking   OCR Engines   OpenGL   ORM   Other Pickers   Parallax List   Parcelables   Particle Systems   Password Inputs   PDF   Permissions   Physics Engines   Platforms   Plugin Frameworks   Preferences   Progress Indicators   ProGuard   Properties   Protocol Buffer   Pull To   Purchases   Push/Pull   QR Codes   Quick Return   Radio Buttons   Range Bars   Ratings   Recycler Views   Resources   REST   Ripple Effects   RSS   Screenshots   Scripting   Scroll Views   SDK   Search Inputs   Security   Sensors   Services   Showcase Views   Signatures   Sliding Panels   Snackbars   SOAP   Social Networks   Spannable   Spinners   Splash Screens   SSH   Static Analysis   Status Bars   Styling   SVG   System   Tags   Task Managers   TDD &   Template Engines   Testing   Testing Tools   Text Formatting   Text Views   Text Watchers   Text-to   Toasts   Toolkits For   Tools   Tooltips   Trainings   TV   Twitter   Updaters   USB   User Stories   Utils   Validation   Video   View Adapters   View Pagers   Views   Watch Face   Wearable Data   Wearables   Weather   Web Tools   Web Views   WebRTC   WebSockets   Wheel Widgets   Wi-Fi   Widgets   Windows   Wizards   XML   XMPP   YAML   ZIP Codes