AspectJ Bytecode Weaving Replaces Boilerplate Network Checks on Android
Android projects accumulate cross-cutting checks—network, permissions, logging—that bloat every screen. Compile-time weaving with AspectJ removes that duplication at the bytecode level, keeping hand-written code focused on business logic while the injected advice handles the guard. The cost is a more complex build and an indirection layer that shows up in decompiled output and stack traces.
A single `@NetworkCheck` annotation, processed by an AspectJ `@Around` advice, intercepts method execution and inspects `ConnectivityManager` before the original body runs. The advice extracts a `Context` from the target object—Activity, View, or Fragment—and either shows a toast and returns null on disconnection or calls `joinPoint.proceed()` to continue. Configuration requires the freefair post-compile-weaving Gradle plugin, an AspectJ runtime dependency, and pointing `AjcWeave` at the platform's `android.jar`.
Decompiling the release APK with jadx confirms the transformation: the original method body is replaced by a synthetic call into a generated static method that wraps the advice. The real business logic gets extracted into a separate `_aroundBody0` method, while the advice method performs the context resolution and network gating before delegating back. This is pure compile-time bytecode manipulation, not runtime reflection.
Beyond network gating, the same pattern applies to permission checks, automatic event tracking, and method-level logging—any cross-cutting concern that would otherwise scatter identical boilerplate across a codebase. The trade-off is longer build times and an extra hop when debugging stack traces.
Bytecode weaving sidesteps the runtime overhead and fragility of reflection-based proxies, but it shifts complexity to the build pipeline—developers must understand what the ajc compiler generates to debug effectively.
The decompiled output reveals that AspectJ does not merely wrap methods; it restructures them into static helpers, which can complicate stack traces and confuse tools that expect original method signatures.
Disabling Gradle configuration cache is a non-trivial concession for larger projects where cache misses already slow down CI, making the build-time cost of AOP more than just the weaving step itself.
Before, I was just like you, but now I wouldn't really recommend using this thing. Young man, give it up.
AspectJ, you mean, or something else?
Yeah, I used to use AspectJ for handling permissions and event tracking too, but not anymore. Just using a singleton is more practical—check the method reference and you immediately know where it is.