Framework
alibaba/ARouter avatar
alibaba/ARouter

ARouter: Alibaba's route table for componentized Android apps

💪 A framework for assisting in the renovation of Android componentization (帮助 Android App 进行组件化改造的路由框架)

14,456 stars2,602 forksJavaApache-2.0

At a glance

What is it?
ARouter replaces direct Intent construction between Android modules with annotated paths, an annotation processor that generates the mapping, and autowired injection into the destination. This is a build-time indirection layer, not networking, and the release history shows its age.
Who is it for?
ARouter earns its place in a large Android app that has already been split into modules and needs to keep module boundaries honest while still navigating between them. It solves path string routing, not module dependency management: it will not break an import cycle for you, and it adds an annotation processor, a runtime dependency and a generated route table to every build.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 25 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 21, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Routing by annotated path instead of an explicit Intent

ARouter's job is narrow. Its README calls it a framework for assisting in the renovation of Android componentization, and the mechanics are one annotation and one call. A screen declares the path it answers to:

java
// Add annotations on pages that support routing (required)
// The path here needs to pay attention to need at least two levels : /xx/xx
@Route(path = "/test/activity")
public class YourActivity extend Activity {
    ...
}

The caller then navigates by string rather than by class reference, which is what removes the compile-time dependency from the calling module to the target module:

java
ARouter.getInstance().build("/test/activity").navigation();

That is the whole idea, and the payoff is real for one specific case: a page in module A opening a page in module B without module A declaring a dependency on module B. The first item in the feature list says it parses standard URLs and injects parameters into the target page automatically, so an external link can land on an internal screen with arguments already bound.

There is a rule worth knowing before you write paths. The comment in that first snippet is explicit that the path needs at least two levels, `/xx/xx`, and the configuration section adds that static route paths must be unique within a module. Duplicate paths across modules are how you get a route table where the winner is not obvious.

What the annotation processor generates at build time

ARouter is not a runtime registry that you populate by hand. The `arouter-compiler/` module is an annotation processor, and it is the piece that makes the whole approach work, because it walks the source set and emits the mapping between paths and classes.

The Gradle snippet that enables it is where the module identity comes from:

gradle
android {
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
}

`AROUTER_MODULE_NAME` is what lets the generated table record which module owns each route, and it is also what the on-demand initialisation feature depends on, since mapping groups are loaded per group rather than all at once.

The repository also carries `arouter-compiler-ksp/` alongside the classic processor, which matters more than the feature list suggests. KSP is the annotation processing path Kotlin projects use now, and having both directories means ARouter is not forcing a choice between the old `annotationProcessor` route and the Kotlin toolchain. There is a separate `arouter-gradle-plugin/` and an `arouter-idea-plugin/`, the latter distributed through the JetBrains plugin repository so navigation from a path string to the class works in the IDE.

Initialisation order, debug mode and the demotion rule

Before routing anything, the SDK has to be initialised, and the README is unusually insistent about ordering:

java
if (isDebug()) {           // These two lines must be written before init, otherwise these configurations will be invalid in the init process
    ARouter.openLog();     // Print log
    ARouter.openDebug();   // Turn on debugging mode (If you are running in InstantRun mode, you must turn on debug mode! Online version needs to be closed, otherwise there is a security risk)
}
ARouter.init(mApplication); // As early as possible, it is recommended to initialize in the Application

Two things are hidden in that snippet. Logging and debug mode are only valid if enabled before `init`, which is why the guard sits outside. And debug mode is described as a security risk in a release build, because it is what lets the framework change behaviour at runtime, which is also the demotion feature in the list: global and local demotion strategies let you override a route at runtime. That is useful for testing a screen you cannot easily reach, and dangerous if it ships enabled.

Parameters then travel through a small fluent builder rather than through a Bundle you assemble by hand:

java
ARouter.getInstance().build("/test/1")
            .withLong("key1", 666L)
            .withString("key3", "888")
            .withObject("key4", new Test("Jack", "Rose"))
            .navigation();

`withObject` is where dependency injection pays off: the object is serialised through the generated code and rehydrated in the destination, which is the same machinery behind `@Autowired` field injection and the `IProvider` service interface used for cross-module communication.

ProGuard rules that the current artefacts already ship

Every route table is code, so obfuscation will break it unless the names survive. The README ships the rules, and the comments around them are unusually candid about what has changed:

text
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep public class com.alibaba.android.arouter.facade.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}

The `routes` and `facade` keeps are the non-negotiable ones, since the generated route map and the public facade are both looked up by name at runtime. The third line above is copied from the README; note that its comment says injector class names are derived from the target class name at runtime, and that current `arouter-api` artefacts package that rule automatically, with the manual keep reserved for older or custom setups. Same for the `IProvider` interface keep, which is only needed when you resolve services by type.

This is the part of ARouter that costs you in release builds, and it is where a team that only read the feature list will get stuck. Get the rules wrong and you get a release-only crash on the first navigation, with a stack trace pointing at reflection rather than at your code.

The AndroidX migration and a major version that has not shipped

The configuration section in the README is the most current part of the document, and it is about a migration rather than a feature. The development line uses AndroidX natively, so consuming applications must set `android.useAndroidX=true`, and ARouter itself does not require Jetifier.

The compatibility advice is precise: projects still on the legacy Support Library should stay on an ARouter 1.x release until the application has moved to AndroidX, and the namespace change is described as a source and binary compatibility boundary, so its release will be handled as a major-version change.

That last sentence is the important one for planning. A major version is announced in the README but does not appear in the release list, whose newest tag is `1.5.1`, named Optimization and Bugfix, published on 2020-10-20. The two earlier tags are `1.5.0` for pretreatment support from 2019-05-09 and `1.4.0` for automatic route doc generation from 2018-08-09.

So the situation in 2026 is a repository with active commits on a `develop` branch and a published artefact line that stopped six years ago. The README's own dependency snippet reflects that, telling you to replace the latest version rather than pinning one:

gradle
dependencies {
    // Replace with the latest version
    compile 'com.alibaba:arouter-api:?'
    annotationProcessor 'com.alibaba:arouter-compiler:?'
    ...
}

If you are evaluating this now, that placeholder is the first thing to resolve, and the JetBrains plugin badge in the version table is the other: the IDE plugin is maintained on a JetBrains numbering scheme rather than these tags, so its version and the library's version do not move together.

What ARouter does not solve about componentization

The feature list is long and largely accurate: multi-module support, interceptors, dependency injection, InstantRun, MultiDex, grouped mappings with on-demand initialisation, automatic registration of activities, interceptors and services, configurable transition animations, fragment support, Kotlin support, generated route documentation, incremental annotation processing and dynamic route metadata. Interceptors are the second thing worth understanding, because they are where routing stops being navigation: an interceptor runs in the chain before the target launches, which is how the classic cases of handling login, collecting statistics and rewriting a jump get implemented without every call site repeating that logic.

What none of that does is manage your dependencies. Componentization fails on import cycles, on a module that quietly compiles against another module's internals, and on a build graph nobody can reason about. ARouter removes the need for a source-level reference from caller to destination, and it does nothing about the rest. Teams that treat it as a componentization strategy stop one step short of the actual problem.

There is also a plain alternative worth naming. Hilt and manual constructor injection with an interface in a shared module handle the dependency injection half without a routing layer, and plain `Intent` extras with an explicit contract handle navigation between two modules you control. ARouter's case is the third thing: many destinations, URLs from outside the app, deep links, and a team that wants the path string to be the single source of truth. If you do not have those, the annotation processor and generated table are overhead you are buying for nothing.

Editorial conclusion

ARouter earns its place in a large Android app that has already been split into modules and needs to keep module boundaries honest while still navigating between them. It solves path string routing, not module dependency management: it will not break an import cycle for you, and it adds an annotation processor, a runtime dependency and a generated route table to every build. The important caveat is that the last tagged release is 1.5.1 from 2020-10-20 while the repository has been pushed on 2026-09-12 on the `develop` branch, so the artefacts you would resolve from Maven are old and the README still says to replace the version with `?`. Before adopting it on new work, resolve a current `com.alibaba:arouter-api` and `arouter-compiler` pair, confirm the KSP path in `arouter-compiler-ksp/` builds under your Kotlin version, and read the namespace note in the configuration section, because that change is explicitly flagged as a major version boundary.

Frequently asked questions

What is ARouter and what problem does it solve?

ARouter is an Android routing framework that lets a screen register a path with a `@Route` annotation and lets callers open it by string instead of by class reference, which removes the source dependency between modules. It also parses standard URLs for deep links and injects parameters into the destination.

How do I add ARouter to an Android project?

Add the `arouter-api` and `arouter-compiler` dependencies, pass `AROUTER_MODULE_NAME: project.getName()` as an annotation processor argument so the generated table records module ownership, then call `ARouter.init(mApplication)` early in your Application class. Any app using the current development line also needs `android.useAndroidX=true` in gradle.properties.

Does ARouter support Kotlin and Jetpack Compose projects?

The README claims full Kotlin support and the repository carries both `arouter-compiler/` and `arouter-compiler-ksp/`, so there is an annotation processing path for Kotlin projects. Neither the README nor the release notes mention Compose navigation, so treat Compose integration as undocumented.

How do I stop ARouter breaking in a release build?

Keep the generated `com.alibaba.android.arouter.routes` and `facade` classes, since the runtime looks them up by name, and turn off `ARouter.openDebug()` outside debug builds because debug mode allows runtime overrides of routes. The current `arouter-api` artefact ships the injector rule itself, and the README keeps the manual `IProvider` keeps for by-type service lookups.

Official sources

  1. alibaba/ARouter on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/alibaba-arouter.svg)](https://hysenlabs.com/projects/alibaba-arouter)