Full Code of alibaba/ARouter for AI

develop 60e6b63c6d30 cached
148 files
329.0 KB
80.3k tokens
426 symbols
1 requests
Download .txt
Showing preview only (374K chars total). Download the full file or copy to clipboard to get everything.
Repository: alibaba/ARouter
Branch: develop
Commit: 60e6b63c6d30
Files: 148
Total size: 329.0 KB

Directory structure:
gitextract_0558mpl4/

├── .github/
│   ├── ISSUE_TEMPLATE.md
│   └── workflows/
│       └── gradle-wrapper-validation.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_CN.md
├── app/
│   ├── build.gradle
│   ├── doc/
│   │   └── debug/
│   │       └── debug.keystore
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── assets/
│           │   └── scheme-test.html
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── demo/
│           │                       ├── MainActivity.java
│           │                       └── SchemeFilterActivity.java
│           └── res/
│               ├── anim/
│               │   ├── slide_in_bottom.xml
│               │   └── slide_out_bottom.xml
│               ├── drawable/
│               │   └── bg_test_area.xml
│               ├── layout/
│               │   └── activity_main.xml
│               └── values/
│                   ├── color.xml
│                   ├── dimens.xml
│                   └── strings.xml
├── arouter-annotation/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── android/
│                           └── arouter/
│                               └── facade/
│                                   ├── annotation/
│                                   │   ├── Autowired.java
│                                   │   ├── Interceptor.java
│                                   │   ├── Param.java
│                                   │   └── Route.java
│                                   ├── enums/
│                                   │   ├── RouteType.java
│                                   │   └── TypeKind.java
│                                   └── model/
│                                       ├── RouteMeta.java
│                                       └── TypeWrapper.java
├── arouter-api/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── android/
│                           └── arouter/
│                               ├── base/
│                               │   └── UniqueKeyTreeMap.java
│                               ├── core/
│                               │   ├── AutowiredLifecycleCallback.java
│                               │   ├── AutowiredServiceImpl.java
│                               │   ├── InstrumentationHook.java
│                               │   ├── InterceptorServiceImpl.java
│                               │   ├── LogisticsCenter.java
│                               │   └── Warehouse.java
│                               ├── exception/
│                               │   ├── HandlerException.java
│                               │   ├── InitException.java
│                               │   └── NoRouteFoundException.java
│                               ├── facade/
│                               │   ├── Postcard.java
│                               │   ├── callback/
│                               │   │   ├── InterceptorCallback.java
│                               │   │   ├── NavCallback.java
│                               │   │   └── NavigationCallback.java
│                               │   ├── service/
│                               │   │   ├── AutowiredService.java
│                               │   │   ├── ClassLoaderService.java
│                               │   │   ├── DegradeService.java
│                               │   │   ├── InterceptorService.java
│                               │   │   ├── PathReplaceService.java
│                               │   │   ├── PretreatmentService.java
│                               │   │   └── SerializationService.java
│                               │   └── template/
│                               │       ├── IInterceptor.java
│                               │       ├── IInterceptorGroup.java
│                               │       ├── ILogger.java
│                               │       ├── IPolicy.java
│                               │       ├── IProvider.java
│                               │       ├── IProviderGroup.java
│                               │       ├── IRouteGroup.java
│                               │       ├── IRouteRoot.java
│                               │       └── ISyringe.java
│                               ├── launcher/
│                               │   ├── ARouter.java
│                               │   └── _ARouter.java
│                               ├── thread/
│                               │   ├── CancelableCountDownLatch.java
│                               │   ├── DefaultPoolExecutor.java
│                               │   └── DefaultThreadFactory.java
│                               └── utils/
│                                   ├── ClassUtils.java
│                                   ├── Consts.java
│                                   ├── DefaultLogger.java
│                                   ├── MapUtils.java
│                                   ├── PackageUtils.java
│                                   └── TextUtils.java
├── arouter-compiler/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── compiler/
│           │                       ├── entity/
│           │                       │   └── RouteDoc.java
│           │                       ├── processor/
│           │                       │   ├── AutowiredProcessor.java
│           │                       │   ├── BaseProcessor.java
│           │                       │   ├── InterceptorProcessor.java
│           │                       │   └── RouteProcessor.java
│           │                       └── utils/
│           │                           ├── Consts.java
│           │                           ├── Logger.java
│           │                           └── TypeUtils.java
│           └── resources/
│               └── META-INF/
│                   └── gradle/
│                       └── incremental.annotation.processors
├── arouter-gradle-plugin/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── groovy/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── register/
│           │                       ├── core/
│           │                       │   ├── RegisterCodeGenerator.groovy
│           │                       │   └── RegisterTransform.groovy
│           │                       ├── launch/
│           │                       │   └── PluginLaunch.groovy
│           │                       └── utils/
│           │                           ├── Logger.groovy
│           │                           ├── ScanSetting.groovy
│           │                           └── ScanUtil.groovy
│           └── resources/
│               └── META-INF/
│                   └── gradle-plugins/
│                       └── com.alibaba.arouter.properties
├── arouter-idea-plugin/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── kotlin/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── idea/
│           │                       └── extensions/
│           │                           └── NavigationLineMarker.kt
│           └── resources/
│               └── META-INF/
│                   └── plugin.xml
├── build.gradle
├── demo/
│   ├── arouter-demo-1.5.2.apk
│   └── arouter-demo.apk
├── gradle/
│   ├── publish.gradle
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── module-java/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── demo/
│           │                       └── module1/
│           │                           ├── BlankFragment.java
│           │                           ├── MainLooper.java
│           │                           ├── TestInterceptor90.java
│           │                           ├── TestModule2Activity.java
│           │                           ├── TestModuleActivity.java
│           │                           ├── TestWebview.java
│           │                           ├── testactivity/
│           │                           │   ├── BaseActivity.java
│           │                           │   ├── Test1Activity.java
│           │                           │   ├── Test2Activity.java
│           │                           │   ├── Test3Activity.java
│           │                           │   ├── Test4Activity.java
│           │                           │   └── TestDynamicActivity.java
│           │                           ├── testinterceptor/
│           │                           │   └── Test1Interceptor.java
│           │                           └── testservice/
│           │                               ├── HelloServiceImpl.java
│           │                               ├── JsonServiceImpl.java
│           │                               └── SingleService.java
│           └── res/
│               ├── layout/
│               │   ├── activity_test1.xml
│               │   ├── activity_test2.xml
│               │   ├── activity_test4.xml
│               │   ├── activity_test_module.xml
│               │   ├── activity_test_module2.xml
│               │   └── activity_test_webview.xml
│               └── values/
│                   ├── dimens.xml
│                   └── strings.xml
├── module-java-export/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── android/
│                           └── arouter/
│                               └── demo/
│                                   └── service/
│                                       ├── Entrance.java
│                                       ├── HelloService.java
│                                       └── model/
│                                           ├── TestObj.java
│                                           ├── TestParcelable.java
│                                           └── TestSerializable.java
├── module-kotlin/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── demo/
│           │                       └── kotlin/
│           │                           ├── KotlinTestActivity.kt
│           │                           └── TestNormalActivity.java
│           └── res/
│               ├── layout/
│               │   ├── activity_kotlin_test.xml
│               │   └── activity_test_normal.xml
│               └── values/
│                   ├── dimens.xml
│                   └── strings.xml
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
## Look at here

- → Did you read the doc carefully
- → Did you add annotation above target activity
- → Did you add annotation processor dependence
- → **Receive only bugs and suggestions**

## 提 issue 前请看

- → 你是否已经熟读 [README](https://github.com/alibaba/ARouter/blob/master/README.md) ?
- → 你是否在每一个包含页面 or 服务的模块中依赖了 compiler sdk
- → **这里不是答疑的地方,仅接受 bug 和建议,答疑请去答疑群**

================================================
FILE: .github/workflows/gradle-wrapper-validation.yml
================================================
name: "Validate Gradle Wrapper"
on: [push, pull_request]

jobs:
  validation:
    name: "Validation"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: gradle/wrapper-validation-action@v1


================================================
FILE: .gitignore
================================================
# Built application files
*.ap_

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Gradle files
.gradle/
build/
/*/build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log

# IDEA Files
.idea
*.iml
/*.ipr
/*.iws
.project
.classpath

# Eclipse Files
/target
*.classpath
*.project
*.settings

app/src/main/res/values/config.xml
app/src/main/res/drawable/yw_1222.jpg

# OS X Files
.DS_Store

map.txt


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright {yyyy} {name of copyright owner}

   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.


================================================
FILE: README.md
================================================
```
    A framework for assisting in the renovation of Android app componentization
```

[中文文档](https://github.com/alibaba/ARouter/blob/master/README_CN.md)

##### [![Join the chat at https://gitter.im/alibaba/ARouter](https://badges.gitter.im/alibaba/ARouter.svg)](https://gitter.im/alibaba/ARouter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](https://www.apache.org/licenses/LICENSE-2.0)

---

#### Lastest version

module|arouter-api|arouter-compiler|arouter-register|arouter-idea-plugin
---|---|---|---|---
version|[![Download](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-api)|[![Download](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-compiler/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-compiler)|[![Download](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-register/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-register)|[![as plugin](https://img.shields.io/jetbrains/plugin/d/11428-arouter-helper.svg)](https://plugins.jetbrains.com/plugin/11428-arouter-helper)

#### Demo

##### [Demo apk](https://github.com/alibaba/ARouter/blob/develop/demo/arouter-demo-1.5.2.apk)、[Demo Gif](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/arouter-demo.gif)

#### I. Feature
1. **Supports direct parsing of standard URLs for jumps and automatic injection of parameters into target pages**
2. **Support for multi-module**
3. **Support for interceptor**
4. **Support for dependency injection**
5. **InstantRun support**
6. **MultiDex support**
7. Mappings are grouped by group, multi-level management, on-demand initialization
8. Supports users to specify global demotion and local demotion strategies
9. Activity, interceptor and service can be automatically registered to the framework
10. Support multiple ways to configure transition animation
11. Support for fragment
12. Full kotlin support (Look at Other#2)
13. **Generate route doc support**
14. **Provide IDE plugin for quick navigation to target class**
15. Support Incremental annotation processing
16. Support register route meta dynamic.

#### II. Classic Case
1. Forward from external URLs to internal pages, and parsing parameters
2. Jump and decoupling between multi-module
3. Intercept jump process, handle login, statistics and other logic
4. Cross-module communication, decouple components by IoC

#### III. Configuration
1. Adding dependencies and configurations
    ``` gradle
    android {
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [AROUTER_MODULE_NAME: project.getName()]
                }
            }
        }
    }

    dependencies {
        // Replace with the latest version
        compile 'com.alibaba:arouter-api:?'
        annotationProcessor 'com.alibaba:arouter-compiler:?'
        ...
    }
    // Old version of gradle plugin (< 2.2), You can use apt plugin, look at 'Other#1'
    // Kotlin configuration reference 'Other#2'
    ```

2. Add annotations
    ``` 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 {
        ...
    }
    ```

3. Initialize the SDK
    ``` 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
    ```

4. Initiate the routing
    ``` java
    // 1. Simple jump within application (Jump via URL in 'Advanced usage')
    ARouter.getInstance().build("/test/activity").navigation();

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

5. Add confusing rules (If Proguard is turn on)
    ``` 
    -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{*;}

    # If you use the byType method to obtain Service, add the following rules to protect the interface:
    -keep interface * implements com.alibaba.android.arouter.facade.template.IProvider

    # If single-type injection is used, that is, no interface is defined to implement IProvider, the following rules need to be added to protect the implementation
    # -keep class * implements com.alibaba.android.arouter.facade.template.IProvider
    ```

6. Using the custom gradle plugin to autoload the routing table
    ```gradle
    apply plugin: 'com.alibaba.arouter'

    buildscript {
        repositories {
            mavenCentral()
        }

        dependencies {
            // Replace with the latest version
            classpath "com.alibaba:arouter-register:?"
        }
    }
    ```

    Optional, use the registration plugin provided by the ARouter to automatically load the routing table(power by [AutoRegister](https://github.com/luckybilly/AutoRegister)). By default, the ARouter will scanned the dex files .
    Performing an auto-registration via the gradle plugin can shorten the initialization time , it should be noted that the plugin must be used with api above 1.3.0!

7. use ide plugin for quick navigation to target class (Optional)

    Search for `ARouter Helper` in the Android Studio plugin market, or directly download the `arouter-idea-plugin` zip installation package listed in the `Latest version` above the documentation, after installation
    plugin without any settings, U can find an icon at the beginning of the jump code. (![navigation](https://raw.githubusercontent.com/alibaba/ARouter/develop/arouter-idea-plugin/src/main/resources/icon/outline_my_location_black_18dp.png)) click the icon to jump to the target class that identifies the path in the code.

#### IV. Advanced usage
1. Jump via URL
    ``` java
    // Create a new Activity for monitoring Scheme events, and then directly pass url to ARouter
    public class SchemeFilterActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            Uri uri = getIntent().getData();
            ARouter.getInstance().build(uri).navigation();
            finish();
        }
    }
    ```

    AndroidManifest.xml
    ``` xml
    <activity android:name=".activity.SchemeFilterActivity">
        <!-- Scheme -->
        <intent-filter>
            <data
                android:host="m.aliyun.com"
                android:scheme="arouter"/>

            <action android:name="android.intent.action.VIEW"/>

            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
        </intent-filter>
    </activity>
    ```

2. Parse the parameters in the URL
    ``` java
    // Declare a field for each parameter and annotate it with @Autowired
    @Route(path = "/test/activity")
    public class Test1Activity extends Activity {
        @Autowired
        public String name;
        @Autowired
        int age;
        @Autowired(name = "girl") // Map different parameters in the URL by name
        boolean boy;
        @Autowired
        TestObj obj;    // Support for parsing custom objects, using json pass in URL

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ARouter.getInstance().inject(this);

            // ARouter will automatically set value of fields
            Log.d("param", name + age + boy);
        }
    }

    // If you need to pass a custom object, Create a new class(Not the custom object class),implement the SerializationService, And use the @Route annotation annotation, E.g:
    @Route(path = "/yourservicegroupname/json")
    public class JsonServiceImpl implements SerializationService {
        @Override
        public void init(Context context) {

        }

        @Override
        public <T> T json2Object(String text, Class<T> clazz) {
            return JSON.parseObject(text, clazz);
        }

        @Override
        public String object2Json(Object instance) {
            return JSON.toJSONString(instance);
        }
    }
    ```

3. Declaration Interceptor (Intercept jump process, AOP)
    ``` java
    // A more classic application is to handle login events during a jump so that there is no need to repeat the login check on the target page.
    // Interceptors will be executed between jumps, multiple interceptors will be executed in order of priority
    @Interceptor(priority = 8, name = "test interceptor")
    public class TestInterceptor implements IInterceptor {
        @Override
        public void process(Postcard postcard, InterceptorCallback callback) {
            ...
            // No problem! hand over control to the framework
            callback.onContinue(postcard);  
            
            // Interrupt routing process
            // callback.onInterrupt(new RuntimeException("Something exception"));      

            // The above two types need to call at least one of them, otherwise it will not continue routing
        }

        @Override
        public void init(Context context) {
            // Interceptor initialization, this method will be called when sdk is initialized, it will only be called once
        }
    }
    ```

4. Processing jump results
    ``` java
    // U can get the result of a single jump
    ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {
        @Override
        public void onFound(Postcard postcard) {
        ...
        }

        @Override
        public void onLost(Postcard postcard) {
        ...
        }
    });
    ```

5. Custom global demotion strategy
    ``` java
    // Implement the DegradeService interface
    @Route(path = "/xxx/xxx")
    public class DegradeServiceImpl implements DegradeService {
        @Override
        public void onLost(Context context, Postcard postcard) {
            // do something.
        }

        @Override
        public void init(Context context) {

        }
    }
    ```

6. Decoupled by dependency injection : Service management -- Exposure services
    ``` java
    // Declaration interface, other components get the service instance through the interface
    public interface HelloService extends IProvider {
        String sayHello(String name);
    }

    @Route(path = "/yourservicegroupname/hello", name = "test service")
    public class HelloServiceImpl implements HelloService {

        @Override
        public String sayHello(String name) {
            return "hello, " + name;
        }

        @Override
        public void init(Context context) {

        }
    }
    ```

7. Decoupled by dependency injection : Service management -- Discovery service
    ``` java
    public class Test {
        @Autowired
        HelloService helloService;

        @Autowired(name = "/yourservicegroupname/hello")
        HelloService helloService2;

        HelloService helloService3;

        HelloService helloService4;

        public Test() {
            ARouter.getInstance().inject(this);
        }

        public void testService() {
            // 1. Use Dependency Injection to discover services, annotate fields with annotations
            helloService.sayHello("Vergil");
            helloService2.sayHello("Vergil");

            // 2. Discovering services using dependency lookup, the following two methods are byName and byType
            helloService3 = ARouter.getInstance().navigation(HelloService.class);
            helloService4 = (HelloService) ARouter.getInstance().build("/yourservicegroupname/hello").navigation();
            helloService3.sayHello("Vergil");
            helloService4.sayHello("Vergil");
        }
    }
    ```
  
8. Pretreatment Service
    ``` java
    @Route(path = "/xxx/xxx")
    public class PretreatmentServiceImpl implements PretreatmentService {
        @Override
        public boolean onPretreatment(Context context, Postcard postcard) {
            // Do something before the navigation, if you need to handle the navigation yourself, the method returns false
        }

        @Override
        public void init(Context context) {
    
        }
    }
    ```

9. Dynamic register route meta
Applicable to apps with plug-in architectures or some scenarios where routing information
needs to be dynamically registered,Dynamic registration can be achieved through the
interface provided by ARouter, The target page and service need not be marked with @Route
annotation,**Only the routing information of the same group can be registered in the same batch**
    ``` java
        ARouter.getInstance().addRouteGroup(new IRouteGroup() {
            @Override
            public void loadInto(Map<String, RouteMeta> atlas) {
                atlas.put("/dynamic/activity",      // path
                    RouteMeta.build(
                        RouteType.ACTIVITY,         // Route type
                        TestDynamicActivity.class,  // Target class
                        "/dynamic/activity",        // Path
                        "dynamic",                  // Group
                        0,                          // not need
                        0                           // Extra tag, Used to mark page feature
                    )
                );
            }
        });
    ```

#### V. More features

1. Other settings in initialization
    ``` java
    ARouter.openLog(); // Open log
    ARouter.openDebug(); // When using InstantRun, you need to open this switch and turn it off after going online. Otherwise, there is a security risk.
    ARouter.printStackTrace(); // Print thread stack when printing logs
    ```

2. API description
    ``` java
    // Build a standard route request
    ARouter.getInstance().build("/home/main").navigation();

    // Build a standard route request, via URI
    Uri uri;
    ARouter.getInstance().build(uri).navigation();

    // Build a standard route request, startActivityForResult
    // The first parameter must be Activity and the second parameter is RequestCode
    ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);

    // Pass Bundle directly
    Bundle params = new Bundle();
    ARouter.getInstance()
        .build("/home/main")
        .with(params)
        .navigation();

    // Set Flag
    ARouter.getInstance()
        .build("/home/main")
        .withFlags();
        .navigation();

    // For fragment
    Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
                        
    // transfer the object 
    ARouter.getInstance()
        .withObject("key", new TestObj("Jack", "Rose"))
        .navigation();

    // Think the interface is not enough, you can directly set parameter into Bundle
    ARouter.getInstance()
            .build("/home/main")
            .getExtra();

    // Transition animation (regular mode)
    ARouter.getInstance()
        .build("/test/activity2")
        .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
        .navigation(this);

    // Transition animation (API16+)
    ActivityOptionsCompat compat = ActivityOptionsCompat.
        makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);

    // ps. makeSceneTransitionAnimation, When using shared elements, you need to pass in the current Activity in the navigation method

    ARouter.getInstance()
        .build("/test/activity2")
        .withOptionsCompat(compat)
        .navigation();
            
    // Use green channel (skip all interceptors)
    ARouter.getInstance().build("/home/main").greenChannel().navigation();

    // Use your own log tool to print logs
    ARouter.setLogger();

    // Use your custom thread pool
    ARouter.setExecutor();
    ```

3. Get the original URI
    ``` java
    String uriStr = getIntent().getStringExtra(ARouter.RAW_URI);
    ```

4. Rewrite URL
    ``` java
    // Implement the PathReplaceService interface
    @Route(path = "/xxx/xxx")
    public class PathReplaceServiceImpl implements PathReplaceService {
        /**
        * For normal path.
        *
        * @param path raw path
        */
        String forString(String path) {
            // Custom logic
            return path;
        }

    /**
        * For uri type.
        *
        * @param uri raw uri
        */
        Uri forUri(Uri uri) {
            // Custom logic
            return url;
        }
    }
    ```

5. Generate router doc
    ``` gradle
    // Edit build.gradle, add option 'AROUTER_GENERATE_DOC = enable'
    // Doc file : build/generated/source/apt/(debug or release)/com/alibaba/android/arouter/docs/arouter-map-of-${moduleName}.json
    android {
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [AROUTER_MODULE_NAME: project.getName(), AROUTER_GENERATE_DOC: "enable"]
                }
            }
        }
    }
    ```

#### VI. Other

1. Old version of gradle plugin configuration
    ``` gradle
    apply plugin: 'com.neenbedankt.android-apt'

    buildscript {
        repositories {
            mavenCentral()
        }

        dependencies {
            classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
        }
    }

    apt {
        arguments {
            AROUTER_MODULE_NAME project.getName();
        }
    }

    dependencies {
        compile 'com.alibaba:arouter-api:x.x.x'
        apt 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }
    ```

2. Kotlin project configuration
    ```
    // You can refer to the wording in the "module-kotlin" module
    apply plugin: 'kotlin-kapt'

    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
        }
    }

    dependencies {
        compile 'com.alibaba:arouter-api:x.x.x'
        kapt 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }
    ```

#### VII. Communication

1. Communication

    1. DingDing group1
    
        ![dingding](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/dingding-group-1.png)

    2. QQ group1
    
        ![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-group-1.png)

    3. QQ group2
        
        ![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-group-2.png)


================================================
FILE: README_CN.md
================================================
```
    一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦
```

[English](https://github.com/alibaba/ARouter/blob/master/README.md)

##### [![Join the chat at https://gitter.im/alibaba/ARouter](https://badges.gitter.im/alibaba/ARouter.svg)](https://gitter.im/alibaba/ARouter?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Hex.pm](https://img.shields.io/hexpm/l/plug.svg)](https://www.apache.org/licenses/LICENSE-2.0)

---

#### 最新版本

模块|arouter-api|arouter-compiler|arouter-register|arouter-idea-plugin
---|---|---|---|---
最新版本|[![Download](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-api)|[![Download](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-compiler/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-compiler)|[![Download](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-register/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.alibaba/arouter-register)|[![as plugin](https://img.shields.io/jetbrains/plugin/d/11428-arouter-helper.svg)](https://plugins.jetbrains.com/plugin/11428-arouter-helper)

#### Demo展示

##### [Demo apk下载](https://github.com/alibaba/ARouter/blob/develop/demo/arouter-demo-1.5.2.apk)、[Demo Gif](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/arouter-demo.gif)

#### 一、功能介绍
1. **支持直接解析标准URL进行跳转,并自动注入参数到目标页面中**
2. **支持多模块工程使用**
3. **支持添加多个拦截器,自定义拦截顺序**
4. **支持依赖注入,可单独作为依赖注入框架使用**
5. **支持InstantRun**
6. **支持MultiDex**(Google方案)
7. 映射关系按组分类、多级管理,按需初始化
8. 支持用户指定全局降级与局部降级策略
9. 页面、拦截器、服务等组件均自动注册到框架
10. 支持多种方式配置转场动画
11. 支持获取Fragment
12. 完全支持Kotlin以及混编(配置见文末 其他#5)
13. **支持第三方 App 加固**(使用 arouter-register 实现自动注册)
14. **支持生成路由文档**
15. **提供 IDE 插件便捷的关联路径和目标类**
16. 支持增量编译(开启文档生成后无法增量编译)
17. 支持动态注册路由信息

#### 二、典型应用
1. 从外部URL映射到内部页面,以及参数传递与解析
2. 跨模块页面跳转,模块间解耦
3. 拦截跳转过程,处理登陆、埋点等逻辑
4. 跨模块API调用,通过控制反转来做组件解耦

#### 三、基础功能
1. 添加依赖和配置
    ``` gradle
    android {
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [AROUTER_MODULE_NAME: project.getName()]
                }
            }
        }
    }

    dependencies {
        // 替换成最新版本, 需要注意的是api
        // 要与compiler匹配使用,均使用最新版可以保证兼容
        compile 'com.alibaba:arouter-api:x.x.x'
        annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }
    // 旧版本gradle插件(< 2.2),可以使用apt插件,配置方法见文末'其他#4'
    // Kotlin配置参考文末'其他#5'
    ```

2. 添加注解
    ``` java
    // 在支持路由的页面上添加注解(必选)
    // 这里的路径需要注意的是至少需要有两级,/xx/xx
    @Route(path = "/test/activity")
    public class YourActivity extend Activity {
        ...
    }
    ```

3. 初始化SDK
    ``` java
    if (isDebug()) {           // 这两行必须写在init之前,否则这些配置在init过程中将无效
        ARouter.openLog();     // 打印日志
        ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
    }
    ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
    ```

4. 发起路由操作
    ``` java
    // 1. 应用内简单的跳转(通过URL跳转在'进阶用法'中)
    ARouter.getInstance().build("/test/activity").navigation();

    // 2. 跳转并携带参数
    ARouter.getInstance().build("/test/1")
                .withLong("key1", 666L)
                .withString("key3", "888")
                .withObject("key4", new Test("Jack", "Rose"))
                .navigation();
    ```

5. 添加混淆规则(如果使用了Proguard)
    ``` 
    -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{*;}

    # 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
    -keep interface * implements com.alibaba.android.arouter.facade.template.IProvider

    # 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
    # -keep class * implements com.alibaba.android.arouter.facade.template.IProvider
    ```

6. 使用 Gradle 插件实现路由表的自动加载 (可选)
    ```gradle
    apply plugin: 'com.alibaba.arouter'

    buildscript {
        repositories {
            mavenCentral()
        }

        dependencies {
            classpath "com.alibaba:arouter-register:?"
        }
    }
    ```

    可选使用,通过 ARouter 提供的注册插件进行路由表的自动加载(power by [AutoRegister](https://github.com/luckybilly/AutoRegister)), 默认通过扫描 dex 的方式
    进行加载通过 gradle 插件进行自动注册可以缩短初始化时间解决应用加固导致无法直接访问
    dex 文件,初始化失败的问题,需要注意的是,该插件必须搭配 api 1.3.0 以上版本使用!

7. 使用 IDE 插件导航到目标类 (可选)

    在 Android Studio 插件市场中搜索 `ARouter Helper`, 或者直接下载文档上方 `最新版本` 中列出的 `arouter-idea-plugin` zip 安装包手动安装,安装后
    插件无任何设置,可以在跳转代码的行首找到一个图标 (![navigation](https://raw.githubusercontent.com/alibaba/ARouter/develop/arouter-idea-plugin/src/main/resources/icon/outline_my_location_black_18dp.png))
    点击该图标,即可跳转到标识了代码中路径的目标类

#### 四、进阶用法
1. 通过URL跳转
    ``` java
    // 新建一个Activity用于监听Scheme事件,之后直接把url传递给ARouter即可
    public class SchemeFilterActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Uri uri = getIntent().getData();
        ARouter.getInstance().build(uri).navigation();
        finish();
        }
    }
    ```

    AndroidManifest.xml
    ``` xml
    <activity android:name=".activity.SchemeFilterActivity">
        <!-- Scheme -->
        <intent-filter>
            <data
            android:host="m.aliyun.com"
            android:scheme="arouter"/>

            <action android:name="android.intent.action.VIEW"/>

            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
        </intent-filter>
    </activity>
    ```

2. 解析参数
    ``` java
    // 为每一个参数声明一个字段,并使用 @Autowired 标注
    // URL中不能传递Parcelable类型数据,通过ARouter api可以传递Parcelable对象
    @Route(path = "/test/activity")
    public class Test1Activity extends Activity {
        @Autowired
        public String name;
        @Autowired
        int age;
        
        // 通过name来映射URL中的不同参数
        @Autowired(name = "girl") 
        boolean boy;
        
        // 支持解析自定义对象,URL中使用json传递
        @Autowired
        TestObj obj;      
        
        // 使用 withObject 传递 List 和 Map 的实现了
        // Serializable 接口的实现类(ArrayList/HashMap)
        // 的时候,接收该对象的地方不能标注具体的实现类类型
        // 应仅标注为 List 或 Map,否则会影响序列化中类型
        // 的判断, 其他类似情况需要同样处理        
        @Autowired
        List<TestObj> list;
        @Autowired
        Map<String, List<TestObj>> map;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ARouter.getInstance().inject(this);

        // ARouter会自动对字段进行赋值,无需主动获取
        Log.d("param", name + age + boy);
        }
    }


    // 如果需要传递自定义对象,新建一个类(并非自定义对象类),然后实现 SerializationService,并使用@Route注解标注(方便用户自行选择序列化方式),例如:
    @Route(path = "/yourservicegroupname/json")
    public class JsonServiceImpl implements SerializationService {
        @Override
        public void init(Context context) {

        }

        @Override
        public <T> T json2Object(String text, Class<T> clazz) {
            return JSON.parseObject(text, clazz);
        }

        @Override
        public String object2Json(Object instance) {
            return JSON.toJSONString(instance);
        }
    }
    ```

3. 声明拦截器(拦截跳转过程,面向切面编程)
    ``` java
    // 比较经典的应用就是在跳转过程中处理登陆事件,这样就不需要在目标页重复做登陆检查
    // 拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行
    @Interceptor(priority = 8, name = "测试用拦截器")
    public class TestInterceptor implements IInterceptor {
        @Override
        public void process(Postcard postcard, InterceptorCallback callback) {
        ...
        callback.onContinue(postcard);  // 处理完成,交还控制权
        // callback.onInterrupt(new RuntimeException("我觉得有点异常"));      // 觉得有问题,中断路由流程

        // 以上两种至少需要调用其中一种,否则不会继续路由
        }

        @Override
        public void init(Context context) {
        // 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次
        }
    }
    ```

4. 处理跳转结果
    ``` java
    // 使用两个参数的navigation方法,可以获取单次跳转的结果
    ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() {
        @Override
        public void onFound(Postcard postcard) {
        ...
        }

        @Override
        public void onLost(Postcard postcard) {
        ...
        }
    });
    ```

5. 自定义全局降级策略
    ``` java
    // 实现DegradeService接口,并加上一个Path内容任意的注解即可
    @Route(path = "/xxx/xxx")
    public class DegradeServiceImpl implements DegradeService {
    @Override
    public void onLost(Context context, Postcard postcard) {
        // do something.
    }

    @Override
    public void init(Context context) {

    }
    }
    ```

6. 为目标页面声明更多信息
    ``` java
    // 我们经常需要在目标页面中配置一些属性,比方说"是否需要登陆"之类的
    // 可以通过 Route 注解中的 extras 属性进行扩展,这个属性是一个 int值,换句话说,单个int有4字节,也就是32位,可以配置32个开关
    // 剩下的可以自行发挥,通过字节操作可以标识32个开关,通过开关标记目标页面的一些属性,在拦截器中可以拿到这个标记进行业务逻辑判断
    @Route(path = "/test/activity", extras = Consts.XXXX)
    ```

7. 通过依赖注入解耦:服务管理(一) 暴露服务
    ``` java
    // 声明接口,其他组件通过接口来调用服务
    public interface HelloService extends IProvider {
        String sayHello(String name);
    }

    // 实现接口
    @Route(path = "/yourservicegroupname/hello", name = "测试服务")
    public class HelloServiceImpl implements HelloService {

        @Override
        public String sayHello(String name) {
        return "hello, " + name;
        }

        @Override
        public void init(Context context) {

        }
    }
    ```

8. 通过依赖注入解耦:服务管理(二) 发现服务
    ``` java
    public class Test {
        @Autowired
        HelloService helloService;

        @Autowired(name = "/yourservicegroupname/hello")
        HelloService helloService2;

        HelloService helloService3;

        HelloService helloService4;

        public Test() {
        ARouter.getInstance().inject(this);
        }

        public void testService() {
        // 1. (推荐)使用依赖注入的方式发现服务,通过注解标注字段,即可使用,无需主动获取
        // Autowired注解中标注name之后,将会使用byName的方式注入对应的字段,不设置name属性,会默认使用byType的方式发现服务(当同一接口有多个实现的时候,必须使用byName的方式发现服务)
        helloService.sayHello("Vergil");
        helloService2.sayHello("Vergil");

        // 2. 使用依赖查找的方式发现服务,主动去发现服务并使用,下面两种方式分别是byName和byType
        helloService3 = ARouter.getInstance().navigation(HelloService.class);
        helloService4 = (HelloService) ARouter.getInstance().build("/yourservicegroupname/hello").navigation();
        helloService3.sayHello("Vergil");
        helloService4.sayHello("Vergil");
        }
    }
    ```

9. 预处理服务
    ``` java
    // 实现 PretreatmentService 接口,并加上一个Path内容任意的注解即可
    @Route(path = "/xxx/xxx")
    public class PretreatmentServiceImpl implements PretreatmentService {
        @Override
        public boolean onPretreatment(Context context, Postcard postcard) {
            // 跳转前预处理,如果需要自行处理跳转,该方法返回 false 即可
        }

        @Override
        public void init(Context context) {
    
        }
    }
    ```

10. 动态注册路由信息
适用于部分插件化架构的App以及需要动态注册路由信息的场景,可以通过 ARouter 提供的接口实现动态注册
路由信息,目标页面和服务可以不标注 @Route 注解,**注意:同一批次仅允许相同 group 的路由信息注册**
    ``` java
        ARouter.getInstance().addRouteGroup(new IRouteGroup() {
            @Override
            public void loadInto(Map<String, RouteMeta> atlas) {
                atlas.put("/dynamic/activity",      // path
                    RouteMeta.build(
                        RouteType.ACTIVITY,         // 路由信息
                        TestDynamicActivity.class,  // 目标的 Class
                        "/dynamic/activity",        // Path
                        "dynamic",                  // Group, 尽量保持和 path 的第一段相同
                        0,                          // 优先级,暂未使用
                        0                           // Extra,用于给页面打标
                    )
                );
            }
        });
    ```
 
#### 五、更多功能

1. 初始化中的其他设置
    ``` java
    ARouter.openLog(); // 开启日志
    ARouter.openDebug(); // 使用InstantRun的时候,需要打开该开关,上线之后关闭,否则有安全风险
    ARouter.printStackTrace(); // 打印日志的时候打印线程堆栈
    ```

2. 详细的API说明
    ``` java
    // 构建标准的路由请求
    ARouter.getInstance().build("/home/main").navigation();

    // 构建标准的路由请求,并指定分组
    ARouter.getInstance().build("/home/main", "ap").navigation();

    // 构建标准的路由请求,通过Uri直接解析
    Uri uri;
    ARouter.getInstance().build(uri).navigation();

    // 构建标准的路由请求,startActivityForResult
    // navigation的第一个参数必须是Activity,第二个参数则是RequestCode
    ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);

    // 直接传递Bundle
    Bundle params = new Bundle();
    ARouter.getInstance()
        .build("/home/main")
        .with(params)
        .navigation();

    // 指定Flag
    ARouter.getInstance()
        .build("/home/main")
        .withFlags();
        .navigation();

    // 获取Fragment
    Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
                        
    // 对象传递
    ARouter.getInstance()
        .withObject("key", new TestObj("Jack", "Rose"))
        .navigation();

    // 觉得接口不够多,可以直接拿出Bundle赋值
    ARouter.getInstance()
            .build("/home/main")
            .getExtra();

    // 转场动画(常规方式)
    ARouter.getInstance()
        .build("/test/activity2")
        .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
        .navigation(this);

    // 转场动画(API16+)
    ActivityOptionsCompat compat = ActivityOptionsCompat.
        makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);

    // ps. makeSceneTransitionAnimation 使用共享元素的时候,需要在navigation方法中传入当前Activity

    ARouter.getInstance()
        .build("/test/activity2")
        .withOptionsCompat(compat)
        .navigation();
            
    // 使用绿色通道(跳过所有的拦截器)
    ARouter.getInstance().build("/home/main").greenChannel().navigation();

    // 使用自己的日志工具打印日志
    ARouter.setLogger();

    // 使用自己提供的线程池
    ARouter.setExecutor();
    ```

3. 获取原始的URI
    ``` java
    String uriStr = getIntent().getStringExtra(ARouter.RAW_URI);
    ```

4. 重写跳转URL
    ``` java
    // 实现PathReplaceService接口,并加上一个Path内容任意的注解即可
    @Route(path = "/xxx/xxx") // 必须标明注解
    public class PathReplaceServiceImpl implements PathReplaceService {
        /**
        * For normal path.
        *
        * @param path raw path
        */
        String forString(String path) {
        return path;    // 按照一定的规则处理之后返回处理后的结果
        }

    /**
        * For uri type.
        *
        * @param uri raw uri
        */
    Uri forUri(Uri uri) {
        return url;    // 按照一定的规则处理之后返回处理后的结果
    }
    }
    ```

5. 生成路由文档
    ``` gradle
    // 更新 build.gradle, 添加参数 AROUTER_GENERATE_DOC = enable
    // 生成的文档路径 : build/generated/source/apt/(debug or release)/com/alibaba/android/arouter/docs/arouter-map-of-${moduleName}.json
    android {
        defaultConfig {
            ...
            javaCompileOptions {
                annotationProcessorOptions {
                    arguments = [AROUTER_MODULE_NAME: project.getName(), AROUTER_GENERATE_DOC: "enable"]
                }
            }
        }
    }
    ```

#### 六、其他

1. 路由中的分组概念

	- SDK中针对所有的路径(/test/1 /test/2)进行分组,分组只有在分组中的某一个路径第一次被访问的时候,该分组才会被初始化
	- 可以通过 @Route 注解主动指定分组,否则使用路径中第一段字符串(/*/)作为分组
	- 注意:一旦主动指定分组之后,应用内路由需要使用 ARouter.getInstance().build(path, group) 进行跳转,手动指定分组,否则无法找到
    ``` java
    @Route(path = "/test/1", group = "app")
    ```

2. 拦截器和服务的异同

	- 拦截器和服务所需要实现的接口不同,但是结构类似,都存在 init(Context context) 方法,但是两者的调用时机不同
	- 拦截器因为其特殊性,会被任何一次路由所触发,拦截器会在ARouter初始化的时候异步初始化,如果第一次路由的时候拦截器还没有初始化结束,路由会等待,直到初始化完成。
	- 服务没有该限制,某一服务可能在App整个生命周期中都不会用到,所以服务只有被调用的时候才会触发初始化操作

3. 旧版本gradle插件的配置方式
    ``` gradle
    apply plugin: 'com.neenbedankt.android-apt'

    buildscript {
        repositories {
            mavenCentral()
        }

        dependencies {
            classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
        }
    }

    apt {
        arguments {
            AROUTER_MODULE_NAME project.getName();
        }
    }

    dependencies {
        compile 'com.alibaba:arouter-api:x.x.x'
        apt 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }
    ```

4. Kotlin项目中的配置方式
    ```
    // 可以参考 module-kotlin 模块中的写法
    apply plugin: 'kotlin-kapt'

    kapt {
        arguments {
            arg("AROUTER_MODULE_NAME", project.getName())
        }
    }

    dependencies {
        compile 'com.alibaba:arouter-api:x.x.x'
        kapt 'com.alibaba:arouter-compiler:x.x.x'
        ...
    }
    ```

#### 七、Q&A

1. "W/ARouter::: ARouter::No postcard![ ]"

    这个Log正常的情况下也会打印出来,如果您的代码中没有实现DegradeService和PathReplaceService的话,因为ARouter本身的一些功能也依赖
    自己提供的Service管理功能,ARouter在跳转的时候会尝试寻找用户实现的PathReplaceService,用于对路径进行重写(可选功能),所以如果您没有
    实现这个服务的话,也会抛出这个日志

    推荐在app中实现DegradeService、PathReplaceService

2. "W/ARouter::: ARouter::There is no route match the path [/xxx/xxx], in group [xxx][ ]"

    - 通常来说这种情况是没有找到目标页面,目标不存在
    - 如果这个页面是存在的,那么您可以按照下面的步骤进行排查
        1. 检查目标页面的注解是否配置正确,正确的注解形式应该是 (@Route(path="/test/test"), 如没有特殊需求,请勿指定group字段,废弃功能)
        2. 检查目标页面所在的模块的gradle脚本中是否依赖了 arouter-compiler sdk (需要注意的是,要使用apt依赖,而不是compile关键字依赖)
        3. 检查编译打包日志,是否出现了形如 ARouter::Compiler >>> xxxxx 的日志,日志中会打印出发现的路由目标
        4. 启动App的时候,开启debug、log(openDebug/openLog), 查看映射表是否已经被扫描出来,形如 D/ARouter::: LogisticsCenter has already been loaded, GroupIndex[4],GroupIndex > 0

3. 开启InstantRun之后无法跳转(高版本Gradle插件下无法跳转)?
        
     因为开启InstantRun之后,很多类文件不会放在原本的dex中,需要单独去加载,ARouter默认不会去加载这些文件,因为安全原因,只有在开启了openDebug之后
     ARouter才回去加载InstantRun产生的文件,所以在以上的情况下,需要在init**之前**调用openDebug
 
4. TransformException:java.util.zip.ZipException: duplicate entry ....
 
     ARouter有按组加载的机制,关于分组可以参考 6-1 部分,ARouter允许一个module中存在多个分组,但是不允许多个module中存在相同的分组,会导致映射文件冲突

5. Kotlin类中的字段无法注入如何解决?
    
    首先,Kotlin中的字段是可以自动注入的,但是注入代码为了减少反射,使用的字段赋值的方式来注入的,Kotlin默认会生成set/get方法,并把属性设置为private
    所以只要保证Kotlin中字段可见性不是private即可,简单解决可以在字段上添加 @JvmField 

6. 通过URL跳转之后,在intent中拿不到参数如何解决?
    
    需要注意的是,如果不使用自动注入,那么可以不写 `ARouter.getInstance().inject(this)`,但是需要取值的字段仍然需要标上 `@Autowired` 注解,因为
    只有标上注解之后,ARouter才能知道以哪一种数据类型提取URL中的参数并放入Intent中,这样您才能在intent中获取到对应的参数
    
7. 新增页面之后,无法跳转?
    
    ARouter加载Dex中的映射文件会有一定耗时,所以ARouter会缓存映射文件,直到新版本升级(版本号或者versionCode变化),而如果是开发版本(ARouter.openDebug()),
    ARouter 每次启动都会重新加载映射文件,开发阶段一定要打开 Debug 功能

#### 八、其他

1. 沟通和交流

    1. 钉钉交流群1
    
        ![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/dingding-group-1.png)

    2. QQ 交流群1
    
        ![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-group-1.png)

    3. QQ 交流群2
        
        ![qq](https://raw.githubusercontent.com/alibaba/ARouter/master/demo/qq-group-2.png)


================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
apply plugin: 'com.alibaba.arouter'

android {
    compileSdkVersion Integer.parseInt(COMPILE_SDK_VERSION)
    buildToolsVersion BUILDTOOLS_VERSION

    defaultConfig {
        minSdkVersion Integer.parseInt(MIN_SDK_VERSION)
        targetSdkVersion Integer.parseInt(TARGET_SDK_VERSION)
        versionName "0.0.1"
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    signingConfigs {
        debug {
            storeFile file("./doc/debug/debug.keystore")
            storePassword "android"
            keyAlias "androiddebugkey"
            keyPassword "android"
        }
    }

    buildTypes {
        debug {
            minifyEnabled false
            signingConfig signingConfigs.debug
        }

        release {
            minifyEnabled true
            signingConfig signingConfigs.debug
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    lintOptions {
        abortOnError false
    }
}

dependencies {
    implementation project(':arouter-api')

    // 开发中依赖对方的 service 包
    implementation project(':module-java-export')
    implementation project(':module-java')

    implementation project(':module-kotlin')

    implementation "com.android.support:support-v4:${SUPPORT_LIB_VERSION}"
    implementation "com.android.support:appcompat-v7:${SUPPORT_LIB_VERSION}"
}

================================================
FILE: app/proguard-rules.pro
================================================
-optimizationpasses 5
-dontpreverify
-dontwarn
-ignorewarnings
-verbose
-overloadaggressively
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-keepattributes EnclosingMethod, *Annotation*, *JavascriptInterface*, InnerClasses, Signature
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

# Android Framework
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

-keepclasseswithmembers class * {
    public <init>(android.content.Context,android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context,android.util.AttributeSet,int);
}

-keepclassmembers class * implements java.io.Serializable {
   static final long serialVersionUID;
   private static final java.io.ObjectStreamField[] serialPersistentFields;
   !static !transient <fields>;
   private void writeObject(java.io.ObjectOutputStream);
   private void readObject(java.io.ObjectInputStream);
   java.lang.Object writeReplace();
   java.lang.Object readResolve();
}

-keep class * extends android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

-keepclasseswithmembernames class * {
    native <methods>;
}

-keepclasseswithmembers,allowshrinking class * {
    native <methods>;
}

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

-keepclassmembers class * extends android.content.Context {
   public void *(android.view.View);
   public void *(android.view.MenuItem);
}

-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);  
}

-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.**{*;}

# ARouter
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
-keep interface * implements com.alibaba.android.arouter.facade.template.IProvider

================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.alibaba.android.arouter.demo">

    <application
        android:allowBackup="false"
        android:icon="@drawable/ic_launcher"
        android:label="ARouter demo"
        android:theme="@style/Base.Theme.AppCompat">
        <activity android:name=".SchemeFilterActivity">

            <!-- Scheme -->
            <intent-filter>
                <data
                    android:host="m.aliyun.com"
                    android:scheme="arouter"/>

                <action android:name="android.intent.action.VIEW"/>

                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
            </intent-filter>

            <!-- App Links -->
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW"/>

                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>

                <data
                    android:host="m.aliyun.com"
                    android:scheme="http"/>
                <data
                    android:host="m.aliyun.com"
                    android:scheme="https"/>
            </intent-filter>
        </activity>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

================================================
FILE: app/src/main/assets/scheme-test.html
================================================
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title></title>
</head>

<body>

<h2>跳转测试</h2>

<h2>自定义Scheme[通常来说都是这样的]</h2>
<p><a href="arouter://m.aliyun.com/test/activity1">arouter://m.aliyun.com/test/activity1</a></p>
<p><a href="arouter://m.aliyun.com/test/activity1?url=https%3a%2f%2fm.abc.com%3fa%3db%26c%3dd">测试URL Encode情况</a></p>
<p><a href="arouter://m.aliyun.com/test/activity1?name=alex&age=18&boy=true&high=180&obj=%7b%22name%22%3a%22jack%22%2c%22id%22%3a666%7d">arouter://m.aliyun.com/test/activity1?name=alex&age=18&boy=true&high=180&obj={"name":"jack","id":"666"}</a></p>
<p><a href="arouter://m.aliyun.com/test/activity2">arouter://m.aliyun.com/test/activity2</a></p>
<p><a href="arouter://m.aliyun.com/test/activity2?key1=value1">arouter://m.aliyun.com/test/activity2?key1=value1</a></p>
<p><a href="arouter://m.aliyun.com/test/activity3?name=alex&age=18&boy=true&high=180">arouter://m.aliyun.com/test/activity3?name=alex&age=18&boy=true&high=180</a></p>

<h2>App Links[防止被App屏蔽]</h2>
<p><a href="http://m.aliyun.com/test/activity1">http://m.aliyun.com/test/activity1</a></p>
<p><a href="http://m.aliyun.com/test/activity2">http://m.aliyun.com/test/activity2</a></p>

</body>
</html>

================================================
FILE: app/src/main/java/com/alibaba/android/arouter/demo/MainActivity.java
================================================
package com.alibaba.android.arouter.demo;

import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.alibaba.android.arouter.demo.module1.testactivity.TestDynamicActivity;
import com.alibaba.android.arouter.demo.service.model.TestObj;
import com.alibaba.android.arouter.demo.service.model.TestParcelable;
import com.alibaba.android.arouter.demo.service.model.TestSerializable;
import com.alibaba.android.arouter.demo.service.HelloService;
import com.alibaba.android.arouter.demo.module1.testservice.SingleService;
import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.callback.NavCallback;
import com.alibaba.android.arouter.facade.enums.RouteType;
import com.alibaba.android.arouter.facade.model.RouteMeta;
import com.alibaba.android.arouter.facade.template.IRouteGroup;
import com.alibaba.android.arouter.launcher.ARouter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    @Override
    public void onClick(View v) {
        // Build test data.
        TestSerializable testSerializable = new TestSerializable("Titanic", 555);
        TestParcelable testParcelable = new TestParcelable("jack", 666);
        TestObj testObj = new TestObj("Rose", 777);
        List<TestObj> objList = new ArrayList<>();
        objList.add(testObj);
        Map<String, List<TestObj>> map = new HashMap<>();
        map.put("testMap", objList);

        switch (v.getId()) {
            case R.id.openLog:
                ARouter.openLog();
//                ARouter.printStackTrace();
                break;
            case R.id.openDebug:
                ARouter.openDebug();
                break;
            case R.id.init:
                // 调试模式不是必须开启,但是为了防止有用户开启了InstantRun,但是
                // 忘了开调试模式,导致无法使用Demo,如果使用了InstantRun,必须在
                // 初始化之前开启调试模式,但是上线前需要关闭,InstantRun仅用于开
                // 发阶段,线上开启调试模式有安全风险,可以使用BuildConfig.DEBUG
                // 来区分环境
                ARouter.openDebug();
                ARouter.init(getApplication());
                break;
            case R.id.normalNavigation:
                ARouter.getInstance()
                        .build("/test/activity2")
                        .navigation();

                // 也可以通过依赖对方提供的二方包来约束入参
                // 非必须,可以通过这种方式调用
                // Entrance.redirect2Test1Activity("张飞", 48, this);
                break;
            case R.id.kotlinNavigation:
                ARouter.getInstance()
                        .build("/kotlin/test")
                        .withString("name", "老王")
                        .withInt("age", 23)
                        .navigation();
                break;
            case R.id.normalNavigationWithParams:
                // ARouter.getInstance()
                //         .build("/test/activity2")
                //         .withString("key1", "value1")
                //         .navigation();

                Uri testUriMix = Uri.parse("arouter://m.aliyun.com/test/activity2");
                ARouter.getInstance().build(testUriMix)
                        .withString("key1", "value1")
                        .navigation();

                break;
            case R.id.oldVersionAnim:
                ARouter.getInstance()
                        .build("/test/activity2")
                        .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
                        .navigation(this);
                break;
            case R.id.newVersionAnim:
                if (Build.VERSION.SDK_INT >= 16) {
                    ActivityOptionsCompat compat = ActivityOptionsCompat.
                            makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);

                    ARouter.getInstance()
                            .build("/test/activity2")
                            .withOptionsCompat(compat)
                            .navigation();
                } else {
                    Toast.makeText(this, "API < 16,不支持新版本动画", Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.interceptor:
                ARouter.getInstance()
                        .build("/test/activity4")
                        .navigation(this, new NavCallback() {
                            @Override
                            public void onArrival(Postcard postcard) {

                            }

                            @Override
                            public void onInterrupt(Postcard postcard) {
                                Log.d("ARouter", "被拦截了");
                            }
                        });
                break;
            case R.id.navByUrl:
                ARouter.getInstance()
                        .build("/test/webview")
                        .withString("url", "file:///android_asset/scheme-test.html")
                        .navigation();
                break;
            case R.id.autoInject:
                ARouter.getInstance().build("/test/activity1")
                        .withString("name", "老王")
                        .withInt("age", 18)
                        .withBoolean("boy", true)
                        .withLong("high", 180)
                        .withString("url", "https://a.b.c")
                        .withSerializable("ser", testSerializable)
                        .withParcelable("pac", testParcelable)
                        .withObject("obj", testObj)
                        .withObject("objList", objList)
                        .withObject("map", map)
                        .navigation();
                break;
            case R.id.navByName:
                ((HelloService) ARouter.getInstance().build("/yourservicegroupname/hello").navigation()).sayHello("mike");
                break;
            case R.id.navByType:
                ARouter.getInstance().navigation(HelloService.class).sayHello("mike");
                break;
            case R.id.navToMoudle1:
                ARouter.getInstance().build("/module/1").navigation();
                break;
            case R.id.navToMoudle2:
                // 这个页面主动指定了Group名
                ARouter.getInstance().build("/module/2", "m2").navigation();
                break;
            case R.id.destroy:
                ARouter.getInstance().destroy();
                break;
            case R.id.failNav:
                ARouter.getInstance().build("/xxx/xxx").navigation(this, new NavCallback() {
                    @Override
                    public void onFound(Postcard postcard) {
                        Log.d("ARouter", "找到了");
                    }

                    @Override
                    public void onLost(Postcard postcard) {
                        Log.d("ARouter", "找不到了");
                    }

                    @Override
                    public void onArrival(Postcard postcard) {
                        Log.d("ARouter", "跳转完了");
                    }

                    @Override
                    public void onInterrupt(Postcard postcard) {
                        Log.d("ARouter", "被拦截了");
                    }
                });
                break;
            case R.id.callSingle:
                ARouter.getInstance().navigation(SingleService.class).sayHello("Mike");
                break;
            case R.id.failNav2:
                ARouter.getInstance().build("/xxx/xxx").navigation();
                break;
            case R.id.failNav3:
                ARouter.getInstance().navigation(MainActivity.class);
                break;
            case R.id.normalNavigation2:
                ARouter.getInstance()
                        .build("/test/activity2")
                        .navigation(this, 666);
                break;
            case R.id.getFragment:
                Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment")
                        .withString("name", "老王")
                        .withInt("age", 18)
                        .withBoolean("boy", true)
                        .withLong("high", 180)
                        .withString("url", "https://a.b.c")
                        .withSerializable("ser", testSerializable)
                        .withParcelable("pac", testParcelable)
                        .withObject("obj", testObj)
                        .withObject("objList", objList)
                        .withObject("map", map).navigation();
                Toast.makeText(this, "找到Fragment:" + fragment.toString(), Toast.LENGTH_SHORT).show();
                break;
            case R.id.addGroup:
                ARouter.getInstance().addRouteGroup(new IRouteGroup() {
                    @Override
                    public void loadInto(Map<String, RouteMeta> atlas) {
                        atlas.put("/dynamic/activity", RouteMeta.build(
                                RouteType.ACTIVITY,
                                TestDynamicActivity.class,
                                "/dynamic/activity",
                                "dynamic", 0, 0));
                    }
                });
                break;
            case R.id.dynamicNavigation:
                // 该页面未配置 Route 注解,动态注册到 ARouter
                ARouter.getInstance().build("/dynamic/activity")
                        .withString("name", "老王")
                        .withInt("age", 18)
                        .withBoolean("boy", true)
                        .withLong("high", 180)
                        .withString("url", "https://a.b.c")
                        .withSerializable("ser", testSerializable)
                        .withParcelable("pac", testParcelable)
                        .withObject("obj", testObj)
                        .withObject("objList", objList)
                        .withObject("map", map).navigation(this);
                break;
            default:
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) {
            case 666:
                Log.e("activityResult", String.valueOf(resultCode));
                break;
            default:
                break;
        }
    }
}


================================================
FILE: app/src/main/java/com/alibaba/android/arouter/demo/SchemeFilterActivity.java
================================================
package com.alibaba.android.arouter.demo;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;

import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.callback.NavCallback;
import com.alibaba.android.arouter.launcher.ARouter;

public class SchemeFilterActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//        直接通过ARouter处理外部Uri
        Uri uri = getIntent().getData();
        ARouter.getInstance().build(uri).navigation(this, new NavCallback() {
            @Override
            public void onArrival(Postcard postcard) {
                finish();
            }
        });
    }
}


================================================
FILE: app/src/main/res/anim/slide_in_bottom.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="2000"
        android:fromYDelta="100%p"
        android:toYDelta="0"/>
    <alpha
        android:duration="2000"
        android:fromAlpha="0.0"
        android:toAlpha="1.0"/>
</set>

================================================
FILE: app/src/main/res/anim/slide_out_bottom.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="2000"
        android:fromYDelta="0%p"
        android:toYDelta="100%p"/>
    <alpha
        android:duration="2000"
        android:fromAlpha="1.0"
        android:toAlpha="0.0"/>
</set>

================================================
FILE: app/src/main/res/drawable/bg_test_area.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke
        android:width="1dp"
        android:color="#FFFFFF"/>
    <corners android:radius="5dp" />
</shape>

================================================
FILE: app/src/main/res/layout/activity_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.alibaba.android.arouter.demo.MainActivity">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_test_area"
            android:orientation="vertical"
            android:padding="@dimen/test_area_padding">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:padding="5dp"
                android:text="基本设置" />

            <Button
                android:id="@+id/openLog"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="打开日志并打印堆栈" />

            <Button
                android:id="@+id/openDebug"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="开启调试模式(InstantRun需要开启)"
                android:visibility="gone" />

            <Button
                android:id="@+id/init"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="初始化ARouter"
                android:textColor="@color/red" />

            <Button
                android:id="@+id/destroy"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="关闭ARouter" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/between_cell"
            android:background="@drawable/bg_test_area"
            android:orientation="vertical"
            android:padding="@dimen/test_area_padding">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="基础功能(请先初始化)" />

            <Button
                android:id="@+id/normalNavigation"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="简单的应用内跳转" />

            <Button
                android:id="@+id/kotlinNavigation"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="跳转到Kotlin页面" />

            <Button
                android:id="@+id/normalNavigation2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="跳转ForResult" />

            <Button
                android:id="@+id/getFragment"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="获取Fragment实例" />

            <Button
                android:id="@+id/normalNavigationWithParams"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="携带参数的应用内跳转" />

            <Button
                android:id="@+id/oldVersionAnim"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="旧版本转场动画" />

            <Button
                android:id="@+id/newVersionAnim"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="新版本转场动画" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/between_cell"
            android:background="@drawable/bg_test_area"
            android:orientation="vertical"
            android:padding="@dimen/test_area_padding">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="进阶用法(请先初始化)" />

            <Button
                android:id="@+id/navByUrl"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="通过URL跳转" />

            <Button
                android:id="@+id/interceptor"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="拦截器测试" />

            <Button
                android:id="@+id/autoInject"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="依赖注入(参照代码)" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/between_cell"
            android:background="@drawable/bg_test_area"
            android:orientation="vertical"
            android:padding="@dimen/test_area_padding">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="服务管理(请先初始化)" />

            <Button
                android:id="@+id/navByName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="ByName调用服务" />

            <Button
                android:id="@+id/navByType"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="ByType调用服务" />

            <Button
                android:id="@+id/callSingle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="调用单类" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/between_cell"
            android:background="@drawable/bg_test_area"
            android:orientation="vertical"
            android:padding="@dimen/test_area_padding">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="多模块测试(请先初始化)" />

            <Button
                android:id="@+id/navToMoudle1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="跳转到模块1" />

            <Button
                android:id="@+id/navToMoudle2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="跳转到模块2" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/between_cell"
            android:background="@drawable/bg_test_area"
            android:orientation="vertical"
            android:padding="@dimen/test_area_padding">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="跳转失败测试(请先初始化)" />

            <Button
                android:id="@+id/failNav"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="跳转失败,单独降级" />

            <Button
                android:id="@+id/failNav2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="跳转失败,全局降级" />

            <Button
                android:id="@+id/failNav3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="服务调用失败" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/between_cell"
            android:background="@drawable/bg_test_area"
            android:orientation="vertical"
            android:padding="@dimen/test_area_padding">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="动态增加路由测试" />

            <Button
                android:id="@+id/addGroup"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="动态增加路由" />

            <Button
                android:id="@+id/dynamicNavigation"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="onClick"
                android:text="动态路由测试" />
        </LinearLayout>
    </LinearLayout>
</ScrollView>

================================================
FILE: app/src/main/res/values/color.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="red">#f15533</color>
</resources>

================================================
FILE: app/src/main/res/values/dimens.xml
================================================
<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">10dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>

    <dimen name="between_cell">3dp</dimen>
    <dimen name="test_area_padding">10dp</dimen>
</resources>


================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
</resources>


================================================
FILE: arouter-annotation/build.gradle
================================================
apply plugin: 'java'

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

apply from: rootProject.file('gradle/publish.gradle')

================================================
FILE: arouter-annotation/gradle.properties
================================================
POM_NAME=ARouter Annotations
POM_ARTIFACT_ID=arouter-annotation
POM_PACKAGING=jar
POM_DESCRIPTION=The annotation used in arouter api
VERSION_NAME=1.0.6

================================================
FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/annotation/Autowired.java
================================================
package com.alibaba.android.arouter.facade.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation for field, which need autowired.
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/20 下午4:26
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.CLASS)
public @interface Autowired {

    // Mark param's name or service name.
    String name() default "";

    // If required, app will be crash when value is null.
    // Primitive type wont be check!
    boolean required() default false;

    // Description of the field
    String desc() default "";
}


================================================
FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/annotation/Interceptor.java
================================================
package com.alibaba.android.arouter.facade.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Mark a interceptor to interception the route.
 * BE ATTENTION : This annotation can be mark the implements of #{IInterceptor} ONLY!!!
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/23 14:03
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Interceptor {
    /**
     * The priority of interceptor, ARouter will be excute them follow the priority.
     */
    int priority();

    /**
     * The name of interceptor, may be used to generate javadoc.
     */
    String name() default "Default";
}


================================================
FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/annotation/Param.java
================================================
package com.alibaba.android.arouter.facade.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Used for mark param of page.
 * THIS ANNOTATION WAS DEPRECATED, USE 'Autowired' PLEASE!
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 2016/11/22 18:01
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.CLASS)
@Deprecated
public @interface Param {
    /**
     * The field name
     */
    String name() default "";

    /**
     * The description of the field
     */
    String desc() default "No desc.";
}


================================================
FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/annotation/Route.java
================================================
package com.alibaba.android.arouter.facade.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Mark a page can be route by router.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/15 下午9:29
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.CLASS)
public @interface Route {

    /**
     * Path of route
     */
    String path();

    /**
     * Used to merger routes, the group name MUST BE USE THE COMMON WORDS !!!
     */
    String group() default "";

    /**
     * Name of route, used to generate javadoc.
     */
    String name() default "";

    /**
     * Extra data, can be set by user.
     * Ps. U should use the integer num sign the switch, by bits. 10001010101010
     */
    int extras() default Integer.MIN_VALUE;

    /**
     * The priority of route.
     */
    int priority() default -1;
}


================================================
FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/RouteType.java
================================================
package com.alibaba.android.arouter.facade.enums;

/**
 * Type of route enum.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/23 22:33
 */
public enum RouteType {
    ACTIVITY(0, "android.app.Activity"),
    SERVICE(1, "android.app.Service"),
    PROVIDER(2, "com.alibaba.android.arouter.facade.template.IProvider"),
    CONTENT_PROVIDER(-1, "android.app.ContentProvider"),
    BOARDCAST(-1, ""),
    METHOD(-1, ""),
    FRAGMENT(-1, "android.app.Fragment"),
    UNKNOWN(-1, "Unknown route type");

    int id;
    String className;

    public int getId() {
        return id;
    }

    public RouteType setId(int id) {
        this.id = id;
        return this;
    }

    public String getClassName() {
        return className;
    }

    public RouteType setClassName(String className) {
        this.className = className;
        return this;
    }

    RouteType(int id, String className) {
        this.id = id;
        this.className = className;
    }

    public static RouteType parse(String name) {
        for (RouteType routeType : RouteType.values()) {
            if (routeType.getClassName().equals(name)) {
                return routeType;
            }
        }

        return UNKNOWN;
    }
}


================================================
FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/TypeKind.java
================================================
package com.alibaba.android.arouter.facade.enums;

/**
 * Kind of field type.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 2017-03-16 19:13:38
 */
public enum TypeKind {
    // Base type
    BOOLEAN,
    BYTE,
    SHORT,
    INT,
    LONG,
    CHAR,
    FLOAT,
    DOUBLE,

    // Other type
    STRING,
    SERIALIZABLE,
    PARCELABLE,
    OBJECT;
}


================================================
FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/RouteMeta.java
================================================
package com.alibaba.android.arouter.facade.model;

import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.facade.enums.RouteType;

import java.util.Map;

import javax.lang.model.element.Element;

/**
 * It contains basic route information.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/24 09:45
 */
public class RouteMeta {
    private RouteType type;         // Type of route
    private Element rawType;        // Raw type of route
    private Class<?> destination;   // Destination
    private String path;            // Path of route
    private String group;           // Group of route
    private int priority = -1;      // The smaller the number, the higher the priority
    private int extra;              // Extra data
    private Map<String, Integer> paramsType;  // Param type
    private String name;

    private Map<String, Autowired> injectConfig;  // Cache inject config.

    public RouteMeta() {
    }

    /**
     * For versions of 'compiler' less than 1.0.7, contain 1.0.7
     *
     * @param type        type
     * @param destination destination
     * @param path        path
     * @param group       group
     * @param priority    priority
     * @param extra       extra
     * @return this
     */
    public static RouteMeta build(RouteType type, Class<?> destination, String path, String group, int priority, int extra) {
        return new RouteMeta(type, null, destination, null, path, group, null, priority, extra);
    }

    /**
     * For versions of 'compiler' greater than 1.0.7
     *
     * @param type        type
     * @param destination destination
     * @param path        path
     * @param group       group
     * @param paramsType  paramsType
     * @param priority    priority
     * @param extra       extra
     * @return this
     */
    public static RouteMeta build(RouteType type, Class<?> destination, String path, String group, Map<String, Integer> paramsType, int priority, int extra) {
        return new RouteMeta(type, null, destination, null, path, group, paramsType, priority, extra);
    }

    /**
     * Type
     *
     * @param route       route
     * @param destination destination
     * @param type        type
     */
    public RouteMeta(Route route, Class<?> destination, RouteType type) {
        this(type, null, destination, route.name(), route.path(), route.group(), null, route.priority(), route.extras());
    }

    /**
     * Type
     *
     * @param route      route
     * @param rawType    rawType
     * @param type       type
     * @param paramsType paramsType
     */
    public RouteMeta(Route route, Element rawType, RouteType type, Map<String, Integer> paramsType) {
        this(type, rawType, null, route.name(), route.path(), route.group(), paramsType, route.priority(), route.extras());
    }

    /**
     * Type
     *
     * @param type        type
     * @param rawType     rawType
     * @param destination destination
     * @param path        path
     * @param group       group
     * @param paramsType  paramsType
     * @param priority    priority
     * @param extra       extra
     */
    public RouteMeta(RouteType type, Element rawType, Class<?> destination, String name, String path, String group, Map<String, Integer> paramsType, int priority, int extra) {
        this.type = type;
        this.name = name;
        this.destination = destination;
        this.rawType = rawType;
        this.path = path;
        this.group = group;
        this.paramsType = paramsType;
        this.priority = priority;
        this.extra = extra;
    }

    public Map<String, Integer> getParamsType() {
        return paramsType;
    }

    public RouteMeta setParamsType(Map<String, Integer> paramsType) {
        this.paramsType = paramsType;
        return this;
    }

    public Map<String, Autowired> getInjectConfig() {
        return injectConfig;
    }

    public void setInjectConfig(Map<String, Autowired> injectConfig) {
        this.injectConfig = injectConfig;
    }

    public Element getRawType() {
        return rawType;
    }

    public RouteMeta setRawType(Element rawType) {
        this.rawType = rawType;
        return this;
    }

    public RouteType getType() {
        return type;
    }

    public RouteMeta setType(RouteType type) {
        this.type = type;
        return this;
    }

    public Class<?> getDestination() {
        return destination;
    }

    public RouteMeta setDestination(Class<?> destination) {
        this.destination = destination;
        return this;
    }

    public String getPath() {
        return path;
    }

    public RouteMeta setPath(String path) {
        this.path = path;
        return this;
    }

    public String getGroup() {
        return group;
    }

    public RouteMeta setGroup(String group) {
        this.group = group;
        return this;
    }

    public int getPriority() {
        return priority;
    }

    public RouteMeta setPriority(int priority) {
        this.priority = priority;
        return this;
    }

    public int getExtra() {
        return extra;
    }

    public RouteMeta setExtra(int extra) {
        this.extra = extra;
        return this;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "RouteMeta{" +
                "type=" + type +
                ", rawType=" + rawType +
                ", destination=" + destination +
                ", path='" + path + '\'' +
                ", group='" + group + '\'' +
                ", priority=" + priority +
                ", extra=" + extra +
                ", paramsType=" + paramsType +
                ", name='" + name + '\'' +
                '}';
    }
}

================================================
FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/TypeWrapper.java
================================================
package com.alibaba.android.arouter.facade.model;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Used for get type of target object.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 17/10/26 11:56:22
 */
public class TypeWrapper<T> {
    protected final Type type;

    protected TypeWrapper() {
        Type superClass = getClass().getGenericSuperclass();

        type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
    }

    public Type getType() {
        return type;
    }
}


================================================
FILE: arouter-api/build.gradle
================================================
apply plugin: 'com.android.library'

android {
    compileSdkVersion Integer.parseInt(COMPILE_SDK_VERSION)
    buildToolsVersion BUILDTOOLS_VERSION

    defaultConfig {
        minSdkVersion Integer.parseInt(MIN_SDK_VERSION)
        targetSdkVersion Integer.parseInt(TARGET_SDK_VERSION)

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

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    buildTypes {
        release {
            debuggable false
            minifyEnabled false
        }

        lintOptions { abortOnError false }
    }
}

dependencies {
    annotationProcessor 'com.alibaba:arouter-compiler:1.5.2'
    api 'com.alibaba:arouter-annotation:1.0.6'
    implementation "com.android.support:support-v4:${SUPPORT_LIB_VERSION}"
}

apply from: rootProject.file('gradle/publish.gradle')

================================================
FILE: arouter-api/gradle.properties
================================================
POM_NAME=ARouter SDK
POM_ARTIFACT_ID=arouter-api
POM_PACKAGING=aar
POM_DESCRIPTION=Route framework for android
VERSION_NAME=1.5.2

================================================
FILE: arouter-api/src/main/AndroidManifest.xml
================================================
<manifest
    package="com.alibaba.android.arouter">
</manifest>


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/base/UniqueKeyTreeMap.java
================================================
package com.alibaba.android.arouter.base;

import java.util.TreeMap;

/**
 * TreeMap with unique key.
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/22 下午5:01
 */
public class UniqueKeyTreeMap<K, V> extends TreeMap<K, V> {
    private String tipText;

    public UniqueKeyTreeMap(String exceptionText) {
        super();

        tipText = exceptionText;
    }

    @Override
    public V put(K key, V value) {
        if (containsKey(key)) {
            throw new RuntimeException(String.format(tipText, key));
        } else {
            return super.put(key, value);
        }
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/AutowiredLifecycleCallback.java
================================================
package com.alibaba.android.arouter.core;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.os.Build;
import android.os.Bundle;

import com.alibaba.android.arouter.launcher.ARouter;

/**
 * LifecycleCallback for autowired.
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/21 上午11:28
 */
@Deprecated
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public class AutowiredLifecycleCallback implements Application.ActivityLifecycleCallbacks {
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        ARouter.getInstance().inject(activity);
    }

    @Override
    public void onActivityStarted(Activity activity) {

    }

    @Override
    public void onActivityResumed(Activity activity) {

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {

    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

    }

    @Override
    public void onActivityDestroyed(Activity activity) {

    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/AutowiredServiceImpl.java
================================================
package com.alibaba.android.arouter.core;

import android.content.Context;
import android.util.LruCache;

import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.facade.service.AutowiredService;
import com.alibaba.android.arouter.facade.template.ISyringe;

import java.util.ArrayList;
import java.util.List;

import static com.alibaba.android.arouter.utils.Consts.SUFFIX_AUTOWIRED;

/**
 * param inject service impl.
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/28 下午6:08
 */
@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
    private LruCache<String, ISyringe> classCache;
    private List<String> blackList;

    @Override
    public void init(Context context) {
        classCache = new LruCache<>(50);
        blackList = new ArrayList<>();
    }

    @Override
    public void autowire(Object instance) {
        doInject(instance, null);
    }

    /**
     * Recursive injection
     *
     * @param instance who call me.
     * @param parent   parent of me.
     */
    private void doInject(Object instance, Class<?> parent) {
        Class<?> clazz = null == parent ? instance.getClass() : parent;

        ISyringe syringe = getSyringe(clazz);
        if (null != syringe) {
            syringe.inject(instance);
        }

        Class<?> superClazz = clazz.getSuperclass();
        // has parent and its not the class of framework.
        if (null != superClazz && !superClazz.getName().startsWith("android")) {
            doInject(instance, superClazz);
        }
    }

    private ISyringe getSyringe(Class<?> clazz) {
        String className = clazz.getName();

        try {
            if (!blackList.contains(className)) {
                ISyringe syringeHelper = classCache.get(className);
                if (null == syringeHelper) {  // No cache.
                    syringeHelper = (ISyringe) Class.forName(clazz.getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
                }
                classCache.put(className, syringeHelper);
                return syringeHelper;
            }
        } catch (Exception e) {
            blackList.add(className);    // This instance need not autowired.
        }

        return null;
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/InstrumentationHook.java
================================================
package com.alibaba.android.arouter.core;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Intent;

import com.alibaba.android.arouter.launcher.ARouter;
import com.alibaba.android.arouter.utils.Consts;
import com.alibaba.android.arouter.utils.TextUtils;

import java.lang.reflect.Field;


/**
 * Use ARouter.getInstance().inject(this) now!
 *
 * Hook the instrumentation, inject values for activity's field.
 * Support normal activity only, not contain unit test.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 2016/11/24 16:42
 */
@Deprecated
public class InstrumentationHook extends Instrumentation {
    /**
     * Hook the instrumentation's newActivity, inject
     * <p>
     * Perform instantiation of the process's {@link Activity} object.  The
     * default implementation provides the normal system behavior.
     *
     * @param cl        The ClassLoader with which to instantiate the object.
     * @param className The name of the class implementing the Activity
     *                  object.
     * @param intent    The Intent object that specified the activity class being
     *                  instantiated.
     * @return The newly instantiated Activity object.
     */
    public Activity newActivity(ClassLoader cl, String className,
                                Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {

//        return (Activity)cl.loadClass(className).newInstance();

        Class<?> targetActivity = cl.loadClass(className);
        Object instanceOfTarget = targetActivity.newInstance();

        if (ARouter.canAutoInject()) {
            String[] autoInjectParams = intent.getStringArrayExtra(ARouter.AUTO_INJECT);
            if (null != autoInjectParams && autoInjectParams.length > 0) {
                for (String paramsName : autoInjectParams) {
                    Object value = intent.getExtras().get(TextUtils.getLeft(paramsName));
                    if (null != value) {
                        try {
                            Field injectField = targetActivity.getDeclaredField(TextUtils.getLeft(paramsName));
                            injectField.setAccessible(true);
                            injectField.set(instanceOfTarget, value);
                        } catch (Exception e) {
                            ARouter.logger.error(Consts.TAG, "Inject values for activity error! [" + e.getMessage() + "]");
                        }
                    }
                }
            }
        }

        return (Activity) instanceOfTarget;
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/InterceptorServiceImpl.java
================================================
package com.alibaba.android.arouter.core;

import android.content.Context;

import com.alibaba.android.arouter.exception.HandlerException;
import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.facade.callback.InterceptorCallback;
import com.alibaba.android.arouter.facade.service.InterceptorService;
import com.alibaba.android.arouter.facade.template.IInterceptor;
import com.alibaba.android.arouter.thread.CancelableCountDownLatch;
import com.alibaba.android.arouter.utils.MapUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.alibaba.android.arouter.launcher.ARouter.logger;
import static com.alibaba.android.arouter.utils.Consts.TAG;

/**
 * All of interceptors
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/23 下午2:09
 */
@Route(path = "/arouter/service/interceptor")
public class InterceptorServiceImpl implements InterceptorService {
    private static boolean interceptorHasInit;
    private static final Object interceptorInitLock = new Object();

    @Override
    public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
        if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {

            checkInterceptorsInitStatus();

            if (!interceptorHasInit) {
                callback.onInterrupt(new HandlerException("Interceptors initialization takes too much time."));
                return;
            }

            LogisticsCenter.executor.execute(new Runnable() {
                @Override
                public void run() {
                    CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
                    try {
                        _execute(0, interceptorCounter, postcard);
                        interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
                        if (interceptorCounter.getCount() > 0) {    // Cancel the navigation this time, if it hasn't return anythings.
                            callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
                        } else if (null != postcard.getTag()) {    // Maybe some exception in the tag.
                            callback.onInterrupt((Throwable) postcard.getTag());
                        } else {
                            callback.onContinue(postcard);
                        }
                    } catch (Exception e) {
                        callback.onInterrupt(e);
                    }
                }
            });
        } else {
            callback.onContinue(postcard);
        }
    }

    /**
     * Excute interceptor
     *
     * @param index    current interceptor index
     * @param counter  interceptor counter
     * @param postcard routeMeta
     */
    private static void _execute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
        if (index < Warehouse.interceptors.size()) {
            IInterceptor iInterceptor = Warehouse.interceptors.get(index);
            iInterceptor.process(postcard, new InterceptorCallback() {
                @Override
                public void onContinue(Postcard postcard) {
                    // Last interceptor excute over with no exception.
                    counter.countDown();
                    _execute(index + 1, counter, postcard);  // When counter is down, it will be execute continue ,but index bigger than interceptors size, then U know.
                }

                @Override
                public void onInterrupt(Throwable exception) {
                    // Last interceptor execute over with fatal exception.

                    postcard.setTag(null == exception ? new HandlerException("No message.") : exception);    // save the exception message for backup.
                    counter.cancel();
                    // Be attention, maybe the thread in callback has been changed,
                    // then the catch block(L207) will be invalid.
                    // The worst is the thread changed to main thread, then the app will be crash, if you throw this exception!
//                    if (!Looper.getMainLooper().equals(Looper.myLooper())) {    // You shouldn't throw the exception if the thread is main thread.
//                        throw new HandlerException(exception.getMessage());
//                    }
                }
            });
        }
    }

    @Override
    public void init(final Context context) {
        LogisticsCenter.executor.execute(new Runnable() {
            @Override
            public void run() {
                if (MapUtils.isNotEmpty(Warehouse.interceptorsIndex)) {
                    for (Map.Entry<Integer, Class<? extends IInterceptor>> entry : Warehouse.interceptorsIndex.entrySet()) {
                        Class<? extends IInterceptor> interceptorClass = entry.getValue();
                        try {
                            IInterceptor iInterceptor = interceptorClass.getConstructor().newInstance();
                            iInterceptor.init(context);
                            Warehouse.interceptors.add(iInterceptor);
                        } catch (Exception ex) {
                            throw new HandlerException(TAG + "ARouter init interceptor error! name = [" + interceptorClass.getName() + "], reason = [" + ex.getMessage() + "]");
                        }
                    }

                    interceptorHasInit = true;

                    logger.info(TAG, "ARouter interceptors init over.");

                    synchronized (interceptorInitLock) {
                        interceptorInitLock.notifyAll();
                    }
                }
            }
        });
    }

    private static void checkInterceptorsInitStatus() {
        synchronized (interceptorInitLock) {
            while (!interceptorHasInit) {
                try {
                    interceptorInitLock.wait(10 * 1000);
                } catch (InterruptedException e) {
                    throw new HandlerException(TAG + "Interceptor init cost too much time error! reason = [" + e.getMessage() + "]");
                }
            }
        }
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java
================================================
package com.alibaba.android.arouter.core;

import android.content.Context;
import android.net.Uri;

import com.alibaba.android.arouter.exception.HandlerException;
import com.alibaba.android.arouter.exception.NoRouteFoundException;
import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.enums.TypeKind;
import com.alibaba.android.arouter.facade.model.RouteMeta;
import com.alibaba.android.arouter.facade.template.IInterceptorGroup;
import com.alibaba.android.arouter.facade.template.IProvider;
import com.alibaba.android.arouter.facade.template.IProviderGroup;
import com.alibaba.android.arouter.facade.template.IRouteGroup;
import com.alibaba.android.arouter.facade.template.IRouteRoot;
import com.alibaba.android.arouter.launcher.ARouter;
import com.alibaba.android.arouter.utils.ClassUtils;
import com.alibaba.android.arouter.utils.Consts;
import com.alibaba.android.arouter.utils.MapUtils;
import com.alibaba.android.arouter.utils.PackageUtils;
import com.alibaba.android.arouter.utils.TextUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;

import static com.alibaba.android.arouter.launcher.ARouter.logger;
import static com.alibaba.android.arouter.utils.Consts.AROUTER_SP_CACHE_KEY;
import static com.alibaba.android.arouter.utils.Consts.AROUTER_SP_KEY_MAP;
import static com.alibaba.android.arouter.utils.Consts.DOT;
import static com.alibaba.android.arouter.utils.Consts.ROUTE_ROOT_PAKCAGE;
import static com.alibaba.android.arouter.utils.Consts.SDK_NAME;
import static com.alibaba.android.arouter.utils.Consts.SEPARATOR;
import static com.alibaba.android.arouter.utils.Consts.SUFFIX_INTERCEPTORS;
import static com.alibaba.android.arouter.utils.Consts.SUFFIX_PROVIDERS;
import static com.alibaba.android.arouter.utils.Consts.SUFFIX_ROOT;
import static com.alibaba.android.arouter.utils.Consts.TAG;

/**
 * LogisticsCenter contains all of the map.
 * <p>
 * 1. Creates instance when it is first used.
 * 2. Handler Multi-Module relationship map(*)
 * 3. Complex logic to solve duplicate group definition
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/23 15:02
 */
public class LogisticsCenter {
    private static Context mContext;
    static ThreadPoolExecutor executor;
    private static boolean registerByPlugin;

    /**
     * arouter-auto-register plugin will generate code inside this method
     * call this method to register all Routers, Interceptors and Providers
     */
    private static void loadRouterMap() {
        registerByPlugin = false;
        // auto generate register code by gradle plugin: arouter-auto-register
        // looks like below:
        // registerRouteRoot(new ARouter..Root..modulejava());
        // registerRouteRoot(new ARouter..Root..modulekotlin());
    }

    /**
     * register by class name
     * Sacrificing a bit of efficiency to solve
     * the problem that the main dex file size is too large
     */
    private static void register(String className) {
        if (!TextUtils.isEmpty(className)) {
            try {
                Class<?> clazz = Class.forName(className);
                Object obj = clazz.getConstructor().newInstance();
                if (obj instanceof IRouteRoot) {
                    registerRouteRoot((IRouteRoot) obj);
                } else if (obj instanceof IProviderGroup) {
                    registerProvider((IProviderGroup) obj);
                } else if (obj instanceof IInterceptorGroup) {
                    registerInterceptor((IInterceptorGroup) obj);
                } else {
                    logger.info(TAG, "register failed, class name: " + className
                            + " should implements one of IRouteRoot/IProviderGroup/IInterceptorGroup.");
                }
            } catch (Exception e) {
                logger.error(TAG,"register class error:" + className, e);
            }
        }
    }

    /**
     * method for arouter-auto-register plugin to register Routers
     * @param routeRoot IRouteRoot implementation class in the package: com.alibaba.android.arouter.core.routers
     */
    private static void registerRouteRoot(IRouteRoot routeRoot) {
        markRegisteredByPlugin();
        if (routeRoot != null) {
            routeRoot.loadInto(Warehouse.groupsIndex);
        }
    }

    /**
     * method for arouter-auto-register plugin to register Interceptors
     * @param interceptorGroup IInterceptorGroup implementation class in the package: com.alibaba.android.arouter.core.routers
     */
    private static void registerInterceptor(IInterceptorGroup interceptorGroup) {
        markRegisteredByPlugin();
        if (interceptorGroup != null) {
            interceptorGroup.loadInto(Warehouse.interceptorsIndex);
        }
    }

    /**
     * method for arouter-auto-register plugin to register Providers
     * @param providerGroup IProviderGroup implementation class in the package: com.alibaba.android.arouter.core.routers
     */
    private static void registerProvider(IProviderGroup providerGroup) {
        markRegisteredByPlugin();
        if (providerGroup != null) {
            providerGroup.loadInto(Warehouse.providersIndex);
        }
    }

    /**
     * mark already registered by arouter-auto-register plugin
     */
    private static void markRegisteredByPlugin() {
        if (!registerByPlugin) {
            registerByPlugin = true;
        }
    }

    /**
     * LogisticsCenter init, load all metas in memory. Demand initialization
     */
    public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
        mContext = context;
        executor = tpe;

        try {
            long startInit = System.currentTimeMillis();
            //load by plugin first
            loadRouterMap();
            if (registerByPlugin) {
                logger.info(TAG, "Load router map by arouter-auto-register plugin.");
            } else {
                Set<String> routerMap;

                // It will rebuild router map every times when debuggable.
                if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
                    logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
                    // These class was generated by arouter-compiler.
                    routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
                    if (!routerMap.isEmpty()) {
                        context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();
                    }

                    PackageUtils.updateVersion(context);    // Save new version name when router map update finishes.
                } else {
                    logger.info(TAG, "Load router map from cache.");
                    routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
                }

                logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
                startInit = System.currentTimeMillis();

                for (String className : routerMap) {
                    if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
                        // This one of root elements, load root.
                        ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
                    } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
                        // Load interceptorMeta
                        ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
                    } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
                        // Load providerIndex
                        ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
                    }
                }
            }

            logger.info(TAG, "Load root element finished, cost " + (System.currentTimeMillis() - startInit) + " ms.");

            if (Warehouse.groupsIndex.size() == 0) {
                logger.error(TAG, "No mapping files were found, check your configuration please!");
            }

            if (ARouter.debuggable()) {
                logger.debug(TAG, String.format(Locale.getDefault(), "LogisticsCenter has already been loaded, GroupIndex[%d], InterceptorIndex[%d], ProviderIndex[%d]", Warehouse.groupsIndex.size(), Warehouse.interceptorsIndex.size(), Warehouse.providersIndex.size()));
            }
        } catch (Exception e) {
            throw new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]");
        }
    }

    /**
     * Build postcard by serviceName
     *
     * @param serviceName interfaceName
     * @return postcard
     */
    public static Postcard buildProvider(String serviceName) {
        RouteMeta meta = Warehouse.providersIndex.get(serviceName);

        if (null == meta) {
            return null;
        } else {
            return new Postcard(meta.getPath(), meta.getGroup());
        }
    }

    /**
     * Completion the postcard by route metas
     *
     * @param postcard Incomplete postcard, should complete by this method.
     */
    public synchronized static void completion(Postcard postcard) {
        if (null == postcard) {
            throw new NoRouteFoundException(TAG + "No postcard!");
        }

        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
        if (null == routeMeta) {
            // Maybe its does't exist, or didn't load.
            if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {
                throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
            } else {
                // Load route and cache it into memory, then delete from metas.
                try {
                    if (ARouter.debuggable()) {
                        logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] starts loading, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
                    }

                    addRouteGroupDynamic(postcard.getGroup(), null);

                    if (ARouter.debuggable()) {
                        logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] has already been loaded, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
                    }
                } catch (Exception e) {
                    throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
                }

                completion(postcard);   // Reload
            }
        } else {
            postcard.setDestination(routeMeta.getDestination());
            postcard.setType(routeMeta.getType());
            postcard.setPriority(routeMeta.getPriority());
            postcard.setExtra(routeMeta.getExtra());

            Uri rawUri = postcard.getUri();
            if (null != rawUri) {   // Try to set params into bundle.
                Map<String, String> resultMap = TextUtils.splitQueryParameters(rawUri);
                Map<String, Integer> paramsType = routeMeta.getParamsType();

                if (MapUtils.isNotEmpty(paramsType)) {
                    // Set value by its type, just for params which annotation by @Param
                    for (Map.Entry<String, Integer> params : paramsType.entrySet()) {
                        setValue(postcard,
                                params.getValue(),
                                params.getKey(),
                                resultMap.get(params.getKey()));
                    }

                    // Save params name which need auto inject.
                    postcard.getExtras().putStringArray(ARouter.AUTO_INJECT, paramsType.keySet().toArray(new String[]{}));
                }

                // Save raw uri
                postcard.withString(ARouter.RAW_URI, rawUri.toString());
            }

            switch (routeMeta.getType()) {
                case PROVIDER:  // if the route is provider, should find its instance
                    // Its provider, so it must implement IProvider
                    Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
                    IProvider instance = Warehouse.providers.get(providerMeta);
                    if (null == instance) { // There's no instance of this provider
                        IProvider provider;
                        try {
                            provider = providerMeta.getConstructor().newInstance();
                            provider.init(mContext);
                            Warehouse.providers.put(providerMeta, provider);
                            instance = provider;
                        } catch (Exception e) {
                            logger.error(TAG, "Init provider failed!", e);
                            throw new HandlerException("Init provider failed!");
                        }
                    }
                    postcard.setProvider(instance);
                    postcard.greenChannel();    // Provider should skip all of interceptors
                    break;
                case FRAGMENT:
                    postcard.greenChannel();    // Fragment needn't interceptors
                default:
                    break;
            }
        }
    }

    /**
     * Set value by known type
     *
     * @param postcard postcard
     * @param typeDef  type
     * @param key      key
     * @param value    value
     */
    private static void setValue(Postcard postcard, Integer typeDef, String key, String value) {
        if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
            return;
        }

        try {
            if (null != typeDef) {
                if (typeDef == TypeKind.BOOLEAN.ordinal()) {
                    postcard.withBoolean(key, Boolean.parseBoolean(value));
                } else if (typeDef == TypeKind.BYTE.ordinal()) {
                    postcard.withByte(key, Byte.parseByte(value));
                } else if (typeDef == TypeKind.SHORT.ordinal()) {
                    postcard.withShort(key, Short.parseShort(value));
                } else if (typeDef == TypeKind.INT.ordinal()) {
                    postcard.withInt(key, Integer.parseInt(value));
                } else if (typeDef == TypeKind.LONG.ordinal()) {
                    postcard.withLong(key, Long.parseLong(value));
                } else if (typeDef == TypeKind.FLOAT.ordinal()) {
                    postcard.withFloat(key, Float.parseFloat(value));
                } else if (typeDef == TypeKind.DOUBLE.ordinal()) {
                    postcard.withDouble(key, Double.parseDouble(value));
                } else if (typeDef == TypeKind.STRING.ordinal()) {
                    postcard.withString(key, value);
                } else if (typeDef == TypeKind.PARCELABLE.ordinal()) {
                    // TODO : How to description parcelable value with string?
                } else if (typeDef == TypeKind.OBJECT.ordinal()) {
                    postcard.withString(key, value);
                } else {    // Compatible compiler sdk 1.0.3, in that version, the string type = 18
                    postcard.withString(key, value);
                }
            } else {
                postcard.withString(key, value);
            }
        } catch (Throwable ex) {
            logger.warning(Consts.TAG, "LogisticsCenter setValue failed! " + ex.getMessage());
        }
    }

    /**
     * Suspend business, clear cache.
     */
    public static void suspend() {
        Warehouse.clear();
    }

    public synchronized static void addRouteGroupDynamic(String groupName, IRouteGroup group) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        if (Warehouse.groupsIndex.containsKey(groupName)){
            // If this group is included, but it has not been loaded
            // load this group first, because dynamic route has high priority.
            Warehouse.groupsIndex.get(groupName).getConstructor().newInstance().loadInto(Warehouse.routes);
            Warehouse.groupsIndex.remove(groupName);
        }

        // cover old group.
        if (null != group) {
            group.loadInto(Warehouse.routes);
        }
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/Warehouse.java
================================================
package com.alibaba.android.arouter.core;

import com.alibaba.android.arouter.base.UniqueKeyTreeMap;
import com.alibaba.android.arouter.facade.model.RouteMeta;
import com.alibaba.android.arouter.facade.template.IInterceptor;
import com.alibaba.android.arouter.facade.template.IProvider;
import com.alibaba.android.arouter.facade.template.IRouteGroup;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Storage of route meta and other data.
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/23 下午1:39
 */
class Warehouse {
    // Cache route and metas
    static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
    static Map<String, RouteMeta> routes = new HashMap<>();

    // Cache provider
    static Map<Class, IProvider> providers = new HashMap<>();
    static Map<String, RouteMeta> providersIndex = new HashMap<>();

    // Cache interceptor
    static Map<Integer, Class<? extends IInterceptor>> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]");
    static List<IInterceptor> interceptors = new ArrayList<>();

    static void clear() {
        routes.clear();
        groupsIndex.clear();
        providers.clear();
        providersIndex.clear();
        interceptors.clear();
        interceptorsIndex.clear();
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/exception/HandlerException.java
================================================
package com.alibaba.android.arouter.exception;

/**
 * 主流程的处理异常
 *
 * @author zhilong <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 15/12/7 上午10:30
 */
public class HandlerException extends RuntimeException {
    public HandlerException(String detailMessage) {
        super(detailMessage);
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/exception/InitException.java
================================================
package com.alibaba.android.arouter.exception;

/**
 * 初始化相关异常
 *
 * @author zhilong <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 2015-12-07 14:17:30
 */
public class InitException extends RuntimeException {
    public InitException(String detailMessage) {
        super(detailMessage);
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/exception/NoRouteFoundException.java
================================================
package com.alibaba.android.arouter.exception;

/**
 * As its name
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/24 10:43
 */
public class NoRouteFoundException extends RuntimeException {
    /**
     * Constructs a new {@code RuntimeException} with the current stack trace
     * and the specified detail message.
     *
     * @param detailMessage the detail message for this exception.
     */
    public NoRouteFoundException(String detailMessage) {
        super(detailMessage);
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java
================================================
package com.alibaba.android.arouter.facade;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.app.ActivityOptionsCompat;
import android.util.SparseArray;

import com.alibaba.android.arouter.facade.callback.NavigationCallback;
import com.alibaba.android.arouter.facade.model.RouteMeta;
import com.alibaba.android.arouter.facade.service.SerializationService;
import com.alibaba.android.arouter.facade.template.IProvider;
import com.alibaba.android.arouter.launcher.ARouter;

import java.io.Serializable;
import java.util.ArrayList;

/**
 * A container that contains the roadmap.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.1.0
 * @since 16/8/22 19:16
 */
public final class Postcard extends RouteMeta {
    // Base
    private Uri uri;
    private Object tag;             // A tag prepare for some thing wrong. inner params, DO NOT USE!
    private Bundle mBundle;         // Data to transform
    private int flags = 0;         // Flags of route
    private int timeout = 300;      // Navigation timeout, TimeUnit.Second
    private IProvider provider;     // It will be set value, if this postcard was provider.
    private boolean greenChannel;
    private SerializationService serializationService;
    private Context context;        // May application or activity, check instance type before use it.
    private String action;

    // Animation
    private Bundle optionsCompat;    // The transition animation of activity
    private int enterAnim = -1;
    private int exitAnim = -1;

    public Bundle getOptionsBundle() {
        return optionsCompat;
    }

    public int getEnterAnim() {
        return enterAnim;
    }

    public int getExitAnim() {
        return exitAnim;
    }

    public IProvider getProvider() {
        return provider;
    }

    public Postcard setProvider(IProvider provider) {
        this.provider = provider;
        return this;
    }

    public Postcard() {
        this(null, null);
    }

    public Postcard(String path, String group) {
        this(path, group, null, null);
    }

    public Postcard(String path, String group, Uri uri, Bundle bundle) {
        setPath(path);
        setGroup(group);
        setUri(uri);
        this.mBundle = (null == bundle ? new Bundle() : bundle);
    }

    public boolean isGreenChannel() {
        return greenChannel;
    }

    public Object getTag() {
        return tag;
    }

    public Postcard setTag(Object tag) {
        this.tag = tag;
        return this;
    }

    public Bundle getExtras() {
        return mBundle;
    }

    public int getTimeout() {
        return timeout;
    }

    /**
     * Set timeout of navigation this time.
     *
     * @param timeout timeout
     * @return this
     */
    public Postcard setTimeout(int timeout) {
        this.timeout = timeout;
        return this;
    }

    public Uri getUri() {
        return uri;
    }

    public Postcard setUri(Uri uri) {
        this.uri = uri;
        return this;
    }

    /**
     * Navigation to the route with path in postcard.
     * No param, will be use application context.
     */
    public Object navigation() {
        return navigation(null);
    }

    /**
     * Navigation to the route with path in postcard.
     *
     * @param context Activity and so on.
     */
    public Object navigation(Context context) {
        return navigation(context, null);
    }

    /**
     * Navigation to the route with path in postcard.
     *
     * @param context Activity and so on.
     */
    public Object navigation(Context context, NavigationCallback callback) {
        return ARouter.getInstance().navigation(context, this, -1, callback);
    }

    /**
     * Navigation to the route with path in postcard.
     *
     * @param mContext    Activity and so on.
     * @param requestCode startActivityForResult's param
     */
    public void navigation(Activity mContext, int requestCode) {
        navigation(mContext, requestCode, null);
    }

    /**
     * Navigation to the route with path in postcard.
     *
     * @param mContext    Activity and so on.
     * @param requestCode startActivityForResult's param
     */
    public void navigation(Activity mContext, int requestCode, NavigationCallback callback) {
        ARouter.getInstance().navigation(mContext, this, requestCode, callback);
    }

    /**
     * Green channel, it will skip all of interceptors.
     *
     * @return this
     */
    public Postcard greenChannel() {
        this.greenChannel = true;
        return this;
    }

    /**
     * BE ATTENTION TO THIS METHOD WAS <P>SET, NOT ADD!</P>
     */
    public Postcard with(Bundle bundle) {
        if (null != bundle) {
            mBundle = bundle;
        }

        return this;
    }

    /**
     * Set special flags controlling how this intent is handled.  Most values
     * here depend on the type of component being executed by the Intent,
     * specifically the FLAG_ACTIVITY_* flags are all for use with
     * {@link Context#startActivity Context.startActivity()} and the
     * FLAG_RECEIVER_* flags are all for use with
     * {@link Context#sendBroadcast(Intent) Context.sendBroadcast()}.
     */
    public Postcard withFlags(int flag) {
        this.flags = flag;
        return this;
    }

    /**
     * Add additional flags to the intent (or with existing flags
     * value).
     *
     * @param flags The new flags to set.
     * @return Returns the same Intent object, for chaining multiple calls
     * into a single statement.
     * @see #withFlags
     */
    public Postcard addFlags(int flags) {
        this.flags |= flags;
        return this;
    }

    public int getFlags() {
        return flags;
    }

    /**
     * Set object value, the value will be convert to string by 'Fastjson'
     *
     * @param key   a String, or null
     * @param value a Object, or null
     * @return current
     */
    public Postcard withObject(@Nullable String key, @Nullable Object value) {
        serializationService = ARouter.getInstance().navigation(SerializationService.class);
        mBundle.putString(key, serializationService.object2Json(value));
        return this;
    }

    // Follow api copy from #{Bundle}

    /**
     * Inserts a String value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a String, or null
     * @return current
     */
    public Postcard withString(@Nullable String key, @Nullable String value) {
        mBundle.putString(key, value);
        return this;
    }

    /**
     * Inserts a Boolean value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a boolean
     * @return current
     */
    public Postcard withBoolean(@Nullable String key, boolean value) {
        mBundle.putBoolean(key, value);
        return this;
    }

    /**
     * Inserts a short value into the mapping of this Bundle, replacing
     * any existing value for the given key.
     *
     * @param key   a String, or null
     * @param value a short
     * @return current
     */
    public Postcard withShort(@Nullable String key, short value) {
        mBundle.putShort(key, value);
        return this;
    }

    /**
     * Inserts an int value into the mapping of this Bundle, replacing
     * any existing value for the given key.
     *
     * @param key   a String, or null
     * @param value an int
     * @return current
     */
    public Postcard withInt(@Nullable String key, int value) {
        mBundle.putInt(key, value);
        return this;
    }

    /**
     * Inserts a long value into the mapping of this Bundle, replacing
     * any existing value for the given key.
     *
     * @param key   a String, or null
     * @param value a long
     * @return current
     */
    public Postcard withLong(@Nullable String key, long value) {
        mBundle.putLong(key, value);
        return this;
    }

    /**
     * Inserts a double value into the mapping of this Bundle, replacing
     * any existing value for the given key.
     *
     * @param key   a String, or null
     * @param value a double
     * @return current
     */
    public Postcard withDouble(@Nullable String key, double value) {
        mBundle.putDouble(key, value);
        return this;
    }

    /**
     * Inserts a byte value into the mapping of this Bundle, replacing
     * any existing value for the given key.
     *
     * @param key   a String, or null
     * @param value a byte
     * @return current
     */
    public Postcard withByte(@Nullable String key, byte value) {
        mBundle.putByte(key, value);
        return this;
    }

    /**
     * Inserts a char value into the mapping of this Bundle, replacing
     * any existing value for the given key.
     *
     * @param key   a String, or null
     * @param value a char
     * @return current
     */
    public Postcard withChar(@Nullable String key, char value) {
        mBundle.putChar(key, value);
        return this;
    }

    /**
     * Inserts a float value into the mapping of this Bundle, replacing
     * any existing value for the given key.
     *
     * @param key   a String, or null
     * @param value a float
     * @return current
     */
    public Postcard withFloat(@Nullable String key, float value) {
        mBundle.putFloat(key, value);
        return this;
    }

    /**
     * Inserts a CharSequence value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a CharSequence, or null
     * @return current
     */
    public Postcard withCharSequence(@Nullable String key, @Nullable CharSequence value) {
        mBundle.putCharSequence(key, value);
        return this;
    }

    /**
     * Inserts a Parcelable value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a Parcelable object, or null
     * @return current
     */
    public Postcard withParcelable(@Nullable String key, @Nullable Parcelable value) {
        mBundle.putParcelable(key, value);
        return this;
    }

    /**
     * Inserts an array of Parcelable values into the mapping of this Bundle,
     * replacing any existing value for the given key.  Either key or value may
     * be null.
     *
     * @param key   a String, or null
     * @param value an array of Parcelable objects, or null
     * @return current
     */
    public Postcard withParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
        mBundle.putParcelableArray(key, value);
        return this;
    }

    /**
     * Inserts a List of Parcelable values into the mapping of this Bundle,
     * replacing any existing value for the given key.  Either key or value may
     * be null.
     *
     * @param key   a String, or null
     * @param value an ArrayList of Parcelable objects, or null
     * @return current
     */
    public Postcard withParcelableArrayList(@Nullable String key, @Nullable ArrayList<? extends Parcelable> value) {
        mBundle.putParcelableArrayList(key, value);
        return this;
    }

    /**
     * Inserts a SparceArray of Parcelable values into the mapping of this
     * Bundle, replacing any existing value for the given key.  Either key
     * or value may be null.
     *
     * @param key   a String, or null
     * @param value a SparseArray of Parcelable objects, or null
     * @return current
     */
    public Postcard withSparseParcelableArray(@Nullable String key, @Nullable SparseArray<? extends Parcelable> value) {
        mBundle.putSparseParcelableArray(key, value);
        return this;
    }

    /**
     * Inserts an ArrayList value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value an ArrayList object, or null
     * @return current
     */
    public Postcard withIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) {
        mBundle.putIntegerArrayList(key, value);
        return this;
    }

    /**
     * Inserts an ArrayList value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value an ArrayList object, or null
     * @return current
     */
    public Postcard withStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) {
        mBundle.putStringArrayList(key, value);
        return this;
    }

    /**
     * Inserts an ArrayList value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value an ArrayList object, or null
     * @return current
     */
    public Postcard withCharSequenceArrayList(@Nullable String key, @Nullable ArrayList<CharSequence> value) {
        mBundle.putCharSequenceArrayList(key, value);
        return this;
    }

    /**
     * Inserts a Serializable value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a Serializable object, or null
     * @return current
     */
    public Postcard withSerializable(@Nullable String key, @Nullable Serializable value) {
        mBundle.putSerializable(key, value);
        return this;
    }

    /**
     * Inserts a byte array value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a byte array object, or null
     * @return current
     */
    public Postcard withByteArray(@Nullable String key, @Nullable byte[] value) {
        mBundle.putByteArray(key, value);
        return this;
    }

    /**
     * Inserts a short array value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a short array object, or null
     * @return current
     */
    public Postcard withShortArray(@Nullable String key, @Nullable short[] value) {
        mBundle.putShortArray(key, value);
        return this;
    }

    /**
     * Inserts a char array value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a char array object, or null
     * @return current
     */
    public Postcard withCharArray(@Nullable String key, @Nullable char[] value) {
        mBundle.putCharArray(key, value);
        return this;
    }

    /**
     * Inserts a float array value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a float array object, or null
     * @return current
     */
    public Postcard withFloatArray(@Nullable String key, @Nullable float[] value) {
        mBundle.putFloatArray(key, value);
        return this;
    }

    /**
     * Inserts a CharSequence array value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a CharSequence array object, or null
     * @return current
     */
    public Postcard withCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) {
        mBundle.putCharSequenceArray(key, value);
        return this;
    }

    /**
     * Inserts a Bundle value into the mapping of this Bundle, replacing
     * any existing value for the given key.  Either key or value may be null.
     *
     * @param key   a String, or null
     * @param value a Bundle object, or null
     * @return current
     */
    public Postcard withBundle(@Nullable String key, @Nullable Bundle value) {
        mBundle.putBundle(key, value);
        return this;
    }

    /**
     * Set normal transition anim
     *
     * @param enterAnim enter
     * @param exitAnim  exit
     * @return current
     */
    public Postcard withTransition(int enterAnim, int exitAnim) {
        this.enterAnim = enterAnim;
        this.exitAnim = exitAnim;
        return this;
    }

    /**
     * Set options compat
     *
     * @param compat compat
     * @return this
     */
    @RequiresApi(16)
    public Postcard withOptionsCompat(ActivityOptionsCompat compat) {
        if (null != compat) {
            this.optionsCompat = compat.toBundle();
        }
        return this;
    }

    @Override
    public String toString() {
        return "Postcard{" +
                "uri=" + uri +
                ", tag=" + tag +
                ", mBundle=" + mBundle +
                ", flags=" + flags +
                ", timeout=" + timeout +
                ", provider=" + provider +
                ", greenChannel=" + greenChannel +
                ", optionsCompat=" + optionsCompat +
                ", enterAnim=" + enterAnim +
                ", exitAnim=" + exitAnim +
                "}\n" +
                super.toString();
    }

    public String getAction() {
        return action;
    }

    public Postcard withAction(String action) {
        this.action = action;
        return this;
    }

    public Context getContext() {
        return context;
    }

    public void setContext(Context context) {
        this.context = context;
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/callback/InterceptorCallback.java
================================================
package com.alibaba.android.arouter.facade.callback;

import com.alibaba.android.arouter.facade.Postcard;

/**
 * The callback of interceptor.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/4 17:36
 */
public interface InterceptorCallback {

    /**
     * Continue process
     *
     * @param postcard route meta
     */
    void onContinue(Postcard postcard);

    /**
     * Interrupt process, pipeline will be destroy when this method called.
     *
     * @param exception Reson of interrupt.
     */
    void onInterrupt(Throwable exception);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/callback/NavCallback.java
================================================
package com.alibaba.android.arouter.facade.callback;

import com.alibaba.android.arouter.facade.Postcard;

/**
 * Easy to use navigation callback.
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/4/10 下午12:59
 */
public abstract class NavCallback implements NavigationCallback {
    @Override
    public void onFound(Postcard postcard) {
        // Do nothing
    }

    @Override
    public void onLost(Postcard postcard) {
        // Do nothing
    }

    @Override
    public abstract void onArrival(Postcard postcard);

    @Override
    public void onInterrupt(Postcard postcard) {
        // Do nothing
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/callback/NavigationCallback.java
================================================
package com.alibaba.android.arouter.facade.callback;

import com.alibaba.android.arouter.facade.Postcard;

/**
 * Callback after navigation.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 2016/9/22 14:15
 */
public interface NavigationCallback {

    /**
     * Callback when find the destination.
     *
     * @param postcard meta
     */
    void onFound(Postcard postcard);

    /**
     * Callback after lose your way.
     *
     * @param postcard meta
     */
    void onLost(Postcard postcard);

    /**
     * Callback after navigation.
     *
     * @param postcard meta
     */
    void onArrival(Postcard postcard);

    /**
     * Callback on interrupt.
     *
     * @param postcard meta
     */
    void onInterrupt(Postcard postcard);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/AutowiredService.java
================================================
package com.alibaba.android.arouter.facade.service;

import com.alibaba.android.arouter.facade.template.IProvider;

/**
 * Service for autowired.
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/28 下午6:06
 */
public interface AutowiredService extends IProvider {

    /**
     * Autowired core.
     * @param instance the instance who need autowired.
     */
    void autowire(Object instance);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/ClassLoaderService.java
================================================
package com.alibaba.android.arouter.facade.service;

import com.alibaba.android.arouter.facade.template.IProvider;

/**
 * Get class by user, maybe someone use InstantRun and other tech will move dex files.
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/23 下午12:16
 */
public interface ClassLoaderService extends IProvider {
    Class<?> forName();
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/DegradeService.java
================================================
package com.alibaba.android.arouter.facade.service;

import android.content.Context;

import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.template.IProvider;

/**
 * Provide degrade service for router, you can do something when route has lost.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 2016/9/22 14:51
 */
public interface DegradeService extends IProvider {

    /**
     * Router has lost.
     *
     * @param postcard meta
     */
    void onLost(Context context, Postcard postcard);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/InterceptorService.java
================================================
package com.alibaba.android.arouter.facade.service;

import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.callback.InterceptorCallback;
import com.alibaba.android.arouter.facade.template.IProvider;

/**
 * Interceptor service
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/23 下午2:06
 */
public interface InterceptorService extends IProvider {

    /**
     * Do interceptions
     */
    void doInterceptions(Postcard postcard, InterceptorCallback callback);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/PathReplaceService.java
================================================
package com.alibaba.android.arouter.facade.service;

import android.net.Uri;

import com.alibaba.android.arouter.facade.template.IProvider;

/**
 * Preprocess your path
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 2016/12/9 16:48
 */
public interface PathReplaceService extends IProvider {

    /**
     * For normal path.
     *
     * @param path raw path
     */
    String forString(String path);

    /**
     * For uri type.
     *
     * @param uri raw uri
     */
    Uri forUri(Uri uri);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/PretreatmentService.java
================================================
package com.alibaba.android.arouter.facade.service;

import android.content.Context;
import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.template.IProvider;

/**
 * Pretreatment service used for check if need navigation.
 *
 * @author zhilong [Contact me.](mailto:zhilong.liu@aliyun.com)
 * @version 1.0
 * @since 2019-05-08 11:53
 */
public interface PretreatmentService extends IProvider {
    /**
     * Do something before navigation.
     *
     * @param context  context
     * @param postcard meta
     * @return if need navigation.
     */
    boolean onPretreatment(Context context, Postcard postcard);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/SerializationService.java
================================================
package com.alibaba.android.arouter.facade.service;

import com.alibaba.android.arouter.facade.template.IProvider;

import java.lang.reflect.Type;

/**
 * Used for parse json string.
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/4/10 下午1:43
 */
public interface SerializationService extends IProvider {

    /**
     * Parse json to object
     *
     * USE @parseObject PLEASE
     *
     * @param input json string
     * @param clazz object type
     * @return instance of object
     */
    @Deprecated
    <T> T json2Object(String input, Class<T> clazz);

    /**
     * Object to json
     *
     * @param instance obj
     * @return json string
     */
    String object2Json(Object instance);

    /**
     * Parse json to object
     *
     * @param input json string
     * @param clazz object type
     * @return instance of object
     */
    <T> T parseObject(String input, Type clazz);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IInterceptor.java
================================================
package com.alibaba.android.arouter.facade.template;

import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.callback.InterceptorCallback;

/**
 * Used for inject custom logic when navigation.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/23 13:56
 */
public interface IInterceptor extends IProvider {

    /**
     * The operation of this interceptor.
     *
     * @param postcard meta
     * @param callback cb
     */
    void process(Postcard postcard, InterceptorCallback callback);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IInterceptorGroup.java
================================================
package com.alibaba.android.arouter.facade.template;

import java.util.Map;

/**
 * Template of interceptor group.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/29 09:51
 */
public interface IInterceptorGroup {
    /**
     * Load interceptor to input
     *
     * @param interceptor input
     */
    void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptor);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/ILogger.java
================================================
package com.alibaba.android.arouter.facade.template;

import com.alibaba.android.arouter.utils.Consts;

/**
 * Logger
 *
 * @author 正纬 <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/5/16 下午5:39
 */
public interface ILogger {

    boolean isShowLog = false;
    boolean isShowStackTrace = false;
    String defaultTag = Consts.TAG;

    void showLog(boolean isShowLog);

    void showStackTrace(boolean isShowStackTrace);

    void debug(String tag, String message);

    void info(String tag, String message);

    void warning(String tag, String message);

    void error(String tag, String message);

    void error(String tag, String message, Throwable e);

    void monitor(String message);

    boolean isMonitorMode();

    String getDefaultTag();
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IPolicy.java
================================================
package com.alibaba.android.arouter.facade.template;

/**
 * Store policy.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/24 10:15
 */
@Deprecated
public interface IPolicy {
    int getFlag();
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IProvider.java
================================================
package com.alibaba.android.arouter.facade.template;

import android.content.Context;

/**
 * Provider interface, base of other interface.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/23 23:08
 */
public interface IProvider {

    /**
     * Do your init work in this method, it well be call when processor has been load.
     *
     * @param context ctx
     */
    void init(Context context);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IProviderGroup.java
================================================
package com.alibaba.android.arouter.facade.template;

import com.alibaba.android.arouter.facade.model.RouteMeta;

import java.util.Map;

/**
 * Template of provider group.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/08/30 12:42
 */
public interface IProviderGroup {
    /**
     * Load providers map to input
     *
     * @param providers input
     */
    void loadInto(Map<String, RouteMeta> providers);
}

================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IRouteGroup.java
================================================
package com.alibaba.android.arouter.facade.template;

import com.alibaba.android.arouter.facade.model.RouteMeta;

import java.util.Map;

/**
 * Group element.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/23 16:37
 */
public interface IRouteGroup {
    /**
     * Fill the atlas with routes in group.
     */
    void loadInto(Map<String, RouteMeta> atlas);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IRouteRoot.java
================================================
package com.alibaba.android.arouter.facade.template;

import java.util.Map;

/**
 * Root element.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/23 16:36
 */
public interface IRouteRoot {

    /**
     * Load routes to input
     * @param routes input
     */
    void loadInto(Map<String, Class<? extends IRouteGroup>> routes);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/ISyringe.java
================================================
package com.alibaba.android.arouter.facade.template;

/**
 * Template of syringe
 *
 * @author zhilong <a href="mailto:zhilong.lzl@alibaba-inc.com">Contact me.</a>
 * @version 1.0
 * @since 2017/2/20 下午4:41
 */
public interface ISyringe {
    void inject(Object target);
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/launcher/ARouter.java
================================================
package com.alibaba.android.arouter.launcher;

import android.app.Application;
import android.content.Context;
import android.net.Uri;

import com.alibaba.android.arouter.exception.InitException;
import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.callback.NavigationCallback;
import com.alibaba.android.arouter.facade.model.RouteMeta;
import com.alibaba.android.arouter.facade.template.ILogger;
import com.alibaba.android.arouter.facade.template.IRouteGroup;
import com.alibaba.android.arouter.utils.Consts;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * ARouter facade
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/16 14:36
 */
public final class ARouter {
    // Key of raw uri
    public static final String RAW_URI = "NTeRQWvye18AkPd6G";
    public static final String AUTO_INJECT = "wmHzgD4lOj5o4241";

    private volatile static ARouter instance = null;
    private volatile static boolean hasInit = false;
    public static ILogger logger;

    private ARouter() {
    }

    /**
     * Init, it must be call before used router.
     */
    public static void init(Application application) {
        if (!hasInit) {
            logger = _ARouter.logger;
            _ARouter.logger.info(Consts.TAG, "ARouter init start.");
            hasInit = _ARouter.init(application);

            if (hasInit) {
                _ARouter.afterInit();
            }

            _ARouter.logger.info(Consts.TAG, "ARouter init over.");
        }
    }

    /**
     * Get instance of router. A
     * All feature U use, will be starts here.
     */
    public static ARouter getInstance() {
        if (!hasInit) {
            throw new InitException("ARouter::Init::Invoke init(context) first!");
        } else {
            if (instance == null) {
                synchronized (ARouter.class) {
                    if (instance == null) {
                        instance = new ARouter();
                    }
                }
            }
            return instance;
        }
    }

    public static synchronized void openDebug() {
        _ARouter.openDebug();
    }

    public static boolean debuggable() {
        return _ARouter.debuggable();
    }

    public static synchronized void openLog() {
        _ARouter.openLog();
    }

    public static synchronized void printStackTrace() {
        _ARouter.printStackTrace();
    }

    public static synchronized void setExecutor(ThreadPoolExecutor tpe) {
        _ARouter.setExecutor(tpe);
    }

    public synchronized void destroy() {
        _ARouter.destroy();
        hasInit = false;
    }

    /**
     * The interface is not stable enough, use 'ARouter.inject();';
     */
    @Deprecated
    public static synchronized void enableAutoInject() {
        _ARouter.enableAutoInject();
    }

    @Deprecated
    public static boolean canAutoInject() {
        return _ARouter.canAutoInject();
    }

    /**
     * The interface is not stable enough, use 'ARouter.inject();';
     */
    @Deprecated
    public static void attachBaseContext() {
        _ARouter.attachBaseContext();
    }

    public static synchronized void monitorMode() {
        _ARouter.monitorMode();
    }

    public static boolean isMonitorMode() {
        return _ARouter.isMonitorMode();
    }

    public static void setLogger(ILogger userLogger) {
        _ARouter.setLogger(userLogger);
    }

    /**
     * Inject params and services.
     */
    public void inject(Object thiz) {
        _ARouter.inject(thiz);
    }

    /**
     * Build the roadmap, draw a postcard.
     *
     * @param path Where you go.
     */
    public Postcard build(String path) {
        return _ARouter.getInstance().build(path);
    }

    /**
     * Build the roadmap, draw a postcard.
     *
     * @param path  Where you go.
     * @param group The group of path.
     */
    @Deprecated
    public Postcard build(String path, String group) {
        return _ARouter.getInstance().build(path, group, false);
    }

    /**
     * Build the roadmap, draw a postcard.
     *
     * @param url the path
     */
    public Postcard build(Uri url) {
        return _ARouter.getInstance().build(url);
    }

    /**
     * Launch the navigation by type
     *
     * @param service interface of service
     * @param <T>     return type
     * @return instance of service
     */
    public <T> T navigation(Class<? extends T> service) {
        return _ARouter.getInstance().navigation(service);
    }

    /**
     * Launch the navigation.
     *
     * @param mContext    .
     * @param postcard    .
     * @param requestCode Set for startActivityForResult
     * @param callback    cb
     */
    public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
        return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
    }

    /**
     * Add route group dynamic.
     * @param group route group.
     * @return add result.
     */
    public boolean addRouteGroup(IRouteGroup group) {
        return _ARouter.getInstance().addRouteGroup(group);
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/launcher/_ARouter.java
================================================
package com.alibaba.android.arouter.launcher;

import android.app.Activity;
import android.app.Application;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.widget.Toast;

import com.alibaba.android.arouter.core.InstrumentationHook;
import com.alibaba.android.arouter.core.LogisticsCenter;
import com.alibaba.android.arouter.exception.HandlerException;
import com.alibaba.android.arouter.exception.InitException;
import com.alibaba.android.arouter.exception.NoRouteFoundException;
import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.callback.InterceptorCallback;
import com.alibaba.android.arouter.facade.callback.NavigationCallback;
import com.alibaba.android.arouter.facade.model.RouteMeta;
import com.alibaba.android.arouter.facade.service.*;
import com.alibaba.android.arouter.facade.template.ILogger;
import com.alibaba.android.arouter.facade.template.IRouteGroup;
import com.alibaba.android.arouter.thread.DefaultPoolExecutor;
import com.alibaba.android.arouter.utils.Consts;
import com.alibaba.android.arouter.utils.DefaultLogger;
import com.alibaba.android.arouter.utils.TextUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * ARouter core (Facade patten)
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/16 14:39
 */
final class _ARouter {
    static ILogger logger = new DefaultLogger(Consts.TAG);
    private volatile static boolean monitorMode = false;
    private volatile static boolean debuggable = false;
    private volatile static boolean autoInject = false;
    private volatile static _ARouter instance = null;
    private volatile static boolean hasInit = false;
    private volatile static ThreadPoolExecutor executor = DefaultPoolExecutor.getInstance();
    private static Handler mHandler;
    private static Context mContext;

    private static InterceptorService interceptorService;

    private _ARouter() {
    }

    protected static synchronized boolean init(Application application) {
        mContext = application;
        LogisticsCenter.init(mContext, executor);
        logger.info(Consts.TAG, "ARouter init success!");
        hasInit = true;
        mHandler = new Handler(Looper.getMainLooper());

        return true;
    }

    /**
     * Destroy arouter, it can be used only in debug mode.
     */
    static synchronized void destroy() {
        if (debuggable()) {
            hasInit = false;
            LogisticsCenter.suspend();
            logger.info(Consts.TAG, "ARouter destroy success!");
        } else {
            logger.error(Consts.TAG, "Destroy can be used in debug mode only!");
        }
    }

    protected static _ARouter getInstance() {
        if (!hasInit) {
            throw new InitException("ARouterCore::Init::Invoke init(context) first!");
        } else {
            if (instance == null) {
                synchronized (_ARouter.class) {
                    if (instance == null) {
                        instance = new _ARouter();
                    }
                }
            }
            return instance;
        }
    }

    static synchronized void openDebug() {
        debuggable = true;
        logger.info(Consts.TAG, "ARouter openDebug");
    }

    static synchronized void openLog() {
        logger.showLog(true);
        logger.info(Consts.TAG, "ARouter openLog");
    }

    @Deprecated
    static synchronized void enableAutoInject() {
        autoInject = true;
    }

    @Deprecated
    static boolean canAutoInject() {
        return autoInject;
    }

    @Deprecated
    static void attachBaseContext() {
        Log.i(Consts.TAG, "ARouter start attachBaseContext");
        try {
            Class<?> mMainThreadClass = Class.forName("android.app.ActivityThread");

            // Get current main thread.
            Method getMainThread = mMainThreadClass.getDeclaredMethod("currentActivityThread");
            getMainThread.setAccessible(true);
            Object currentActivityThread = getMainThread.invoke(null);

            // The field contain instrumentation.
            Field mInstrumentationField = mMainThreadClass.getDeclaredField("mInstrumentation");
            mInstrumentationField.setAccessible(true);

            // Hook current instrumentation
            mInstrumentationField.set(currentActivityThread, new InstrumentationHook());
            Log.i(Consts.TAG, "ARouter hook instrumentation success!");
        } catch (Exception ex) {
            Log.e(Consts.TAG, "ARouter hook instrumentation failed! [" + ex.getMessage() + "]");
        }
    }

    static synchronized void printStackTrace() {
        logger.showStackTrace(true);
        logger.info(Consts.TAG, "ARouter printStackTrace");
    }

    static synchronized void setExecutor(ThreadPoolExecutor tpe) {
        executor = tpe;
    }

    static synchronized void monitorMode() {
        monitorMode = true;
        logger.info(Consts.TAG, "ARouter monitorMode on");
    }

    static boolean isMonitorMode() {
        return monitorMode;
    }

    static boolean debuggable() {
        return debuggable;
    }

    static void setLogger(ILogger userLogger) {
        if (null != userLogger) {
            logger = userLogger;
        }
    }

    static void inject(Object thiz) {
        AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
        if (null != autowiredService) {
            autowiredService.autowire(thiz);
        }
    }

    /**
     * Build postcard by path and default group
     */
    protected Postcard build(String path) {
        if (TextUtils.isEmpty(path)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                path = pService.forString(path);
            }
            return build(path, extractGroup(path), true);
        }
    }

    /**
     * Build postcard by uri
     */
    protected Postcard build(Uri uri) {
        if (null == uri || TextUtils.isEmpty(uri.toString())) {
            throw new HandlerException(Consts.TAG + "Parameter invalid!");
        } else {
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                uri = pService.forUri(uri);
            }
            return new Postcard(uri.getPath(), extractGroup(uri.getPath()), uri, null);
        }
    }

    /**
     * Build postcard by path and group
     */
    protected Postcard build(String path, String group, Boolean afterReplace) {
        if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
            if (!afterReplace) {
                PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
                if (null != pService) {
                    path = pService.forString(path);
                }
            }
            return new Postcard(path, group);
        }
    }

    /**
     * Extract the default group from path.
     */
    private String extractGroup(String path) {
        if (TextUtils.isEmpty(path) || !path.startsWith("/")) {
            throw new HandlerException(Consts.TAG + "Extract the default group failed, the path must be start with '/' and contain more than 2 '/'!");
        }

        try {
            String defaultGroup = path.substring(1, path.indexOf("/", 1));
            if (TextUtils.isEmpty(defaultGroup)) {
                throw new HandlerException(Consts.TAG + "Extract the default group failed! There's nothing between 2 '/'!");
            } else {
                return defaultGroup;
            }
        } catch (Exception e) {
            logger.warning(Consts.TAG, "Failed to extract default group! " + e.getMessage());
            return null;
        }
    }

    static void afterInit() {
        // Trigger interceptor init, use byName.
        interceptorService = (InterceptorService) ARouter.getInstance().build("/arouter/service/interceptor").navigation();
    }

    protected <T> T navigation(Class<? extends T> service) {
        try {
            Postcard postcard = LogisticsCenter.buildProvider(service.getName());

            // Compatible 1.0.5 compiler sdk.
            // Earlier versions did not use the fully qualified name to get the service
            if (null == postcard) {
                // No service, or this service in old version.
                postcard = LogisticsCenter.buildProvider(service.getSimpleName());
            }

            if (null == postcard) {
                return null;
            }

            // Set application to postcard.
            postcard.setContext(mContext);

            LogisticsCenter.completion(postcard);
            return (T) postcard.getProvider();
        } catch (NoRouteFoundException ex) {
            logger.warning(Consts.TAG, ex.getMessage());
            return null;
        }
    }

    /**
     * Use router navigation.
     *
     * @param context     Activity or null.
     * @param postcard    Route metas
     * @param requestCode RequestCode
     * @param callback    cb
     */
    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
        if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
            // Pretreatment failed, navigation canceled.
            return null;
        }

        // Set context to postcard.
        postcard.setContext(null == context ? mContext : context);

        try {
            LogisticsCenter.completion(postcard);
        } catch (NoRouteFoundException ex) {
            logger.warning(Consts.TAG, ex.getMessage());

            if (debuggable()) {
                // Show friendly tips for user.
                runInMainThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(mContext, "There's no route matched!\n" +
                                " Path = [" + postcard.getPath() + "]\n" +
                                " Group = [" + postcard.getGroup() + "]", Toast.LENGTH_LONG).show();
                    }
                });
            }

            if (null != callback) {
                callback.onLost(postcard);
            } else {
                // No callback for this invoke, then we use the global degrade service.
                DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
                if (null != degradeService) {
                    degradeService.onLost(context, postcard);
                }
            }

            return null;
        }

        if (null != callback) {
            callback.onFound(postcard);
        }

        if (!postcard.isGreenChannel()) {   // It must be run in async thread, maybe interceptor cost too mush time made ANR.
            interceptorService.doInterceptions(postcard, new InterceptorCallback() {
                /**
                 * Continue process
                 *
                 * @param postcard route meta
                 */
                @Override
                public void onContinue(Postcard postcard) {
                    _navigation(postcard, requestCode, callback);
                }

                /**
                 * Interrupt process, pipeline will be destory when this method called.
                 *
                 * @param exception Reson of interrupt.
                 */
                @Override
                public void onInterrupt(Throwable exception) {
                    if (null != callback) {
                        callback.onInterrupt(postcard);
                    }

                    logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
                }
            });
        } else {
            return _navigation(postcard, requestCode, callback);
        }

        return null;
    }

    private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        final Context currentContext = postcard.getContext();

        switch (postcard.getType()) {
            case ACTIVITY:
                // Build intent
                final Intent intent = new Intent(currentContext, postcard.getDestination());
                intent.putExtras(postcard.getExtras());

                // Set flags.
                int flags = postcard.getFlags();
                if (0 != flags) {
                    intent.setFlags(flags);
                }

                // Non activity, need FLAG_ACTIVITY_NEW_TASK
                if (!(currentContext instanceof Activity)) {
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                }

                // Set Actions
                String action = postcard.getAction();
                if (!TextUtils.isEmpty(action)) {
                    intent.setAction(action);
                }

                // Navigation in main looper.
                runInMainThread(new Runnable() {
                    @Override
                    public void run() {
                        startActivity(requestCode, currentContext, intent, postcard, callback);
                    }
                });

                break;
            case PROVIDER:
                return postcard.getProvider();
            case BOARDCAST:
            case CONTENT_PROVIDER:
            case FRAGMENT:
                Class<?> fragmentMeta = postcard.getDestination();
                try {
                    Object instance = fragmentMeta.getConstructor().newInstance();
                    if (instance instanceof Fragment) {
                        ((Fragment) instance).setArguments(postcard.getExtras());
                    } else if (instance instanceof android.support.v4.app.Fragment) {
                        ((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());
                    }

                    return instance;
                } catch (Exception ex) {
                    logger.error(Consts.TAG, "Fetch fragment instance error, " + TextUtils.formatStackTrace(ex.getStackTrace()));
                }
            case METHOD:
            case SERVICE:
            default:
                return null;
        }

        return null;
    }

    /**
     * Be sure execute in main thread.
     *
     * @param runnable code
     */
    private void runInMainThread(Runnable runnable) {
        if (Looper.getMainLooper().getThread() != Thread.currentThread()) {
            mHandler.post(runnable);
        } else {
            runnable.run();
        }
    }

    /**
     * Start activity
     *
     * @see ActivityCompat
     */
    private void startActivity(int requestCode, Context currentContext, Intent intent, Postcard postcard, NavigationCallback callback) {
        if (requestCode >= 0) {  // Need start for result
            if (currentContext instanceof Activity) {
                ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle());
            } else {
                logger.warning(Consts.TAG, "Must use [navigation(activity, ...)] to support [startActivityForResult]");
            }
        } else {
            ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());
        }

        if ((-1 != postcard.getEnterAnim() && -1 != postcard.getExitAnim()) && currentContext instanceof Activity) {    // Old version.
            ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
        }

        if (null != callback) { // Navigation over.
            callback.onArrival(postcard);
        }
    }

    boolean addRouteGroup(IRouteGroup group) {
        if (null == group) {
            return false;
        }

        String groupName = null;

        try {
            // Extract route meta.
            Map<String, RouteMeta> dynamicRoute = new HashMap<>();
            group.loadInto(dynamicRoute);

            // Check route meta.
            for (Map.Entry<String, RouteMeta> route : dynamicRoute.entrySet()) {
                String path = route.getKey();
                String groupByExtract = extractGroup(path);
                RouteMeta meta = route.getValue();

                if (null == groupName) {
                    groupName = groupByExtract;
                }

                if (null == groupName || !groupName.equals(groupByExtract) || !groupName.equals(meta.getGroup())) {
                    // Group name not consistent
                    return false;
                }
            }

            LogisticsCenter.addRouteGroupDynamic(groupName, group);

            logger.info(Consts.TAG, "Add route group [" + groupName + "] finish, " + dynamicRoute.size() + " new route meta.");

            return true;
        } catch (Exception exception) {
            logger.error(Consts.TAG, "Add route group dynamic exception!", exception);
        }

        return false;
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/thread/CancelableCountDownLatch.java
================================================
package com.alibaba.android.arouter.thread;

import java.util.concurrent.CountDownLatch;

/**
 * As its name.
 *
 * @author Alex <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/8/29 15:48
 */
public class CancelableCountDownLatch extends CountDownLatch {
    /**
     * Constructs a {@code CountDownLatch} initialized with the given count.
     *
     * @param count the number of times {@link #countDown} must be invoked
     *              before threads can pass through {@link #await}
     * @throws IllegalArgumentException if {@code count} is negative
     */
    public CancelableCountDownLatch(int count) {
        super(count);
    }

    public void cancel() {
        while (getCount() > 0) {
            countDown();
        }
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/thread/DefaultPoolExecutor.java
================================================
package com.alibaba.android.arouter.thread;

import com.alibaba.android.arouter.launcher.ARouter;
import com.alibaba.android.arouter.utils.Consts;
import com.alibaba.android.arouter.utils.TextUtils;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Executors
 *
 * @author 正纬 <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/4/28 下午4:07
 */
public class DefaultPoolExecutor extends ThreadPoolExecutor {
    //    Thread args
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int INIT_THREAD_COUNT = CPU_COUNT + 1;
    private static final int MAX_THREAD_COUNT = INIT_THREAD_COUNT;
    private static final long SURPLUS_THREAD_LIFE = 30L;

    private static volatile DefaultPoolExecutor instance;

    public static DefaultPoolExecutor getInstance() {
        if (null == instance) {
            synchronized (DefaultPoolExecutor.class) {
                if (null == instance) {
                    instance = new DefaultPoolExecutor(
                            INIT_THREAD_COUNT,
                            MAX_THREAD_COUNT,
                            SURPLUS_THREAD_LIFE,
                            TimeUnit.SECONDS,
                            new ArrayBlockingQueue<Runnable>(64),
                            new DefaultThreadFactory());
                }
            }
        }
        return instance;
    }

    private DefaultPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                ARouter.logger.error(Consts.TAG, "Task rejected, too many task!");
            }
        });
    }

    /*
     *  线程执行结束,顺便看一下有么有什么乱七八糟的异常
     *
     * @param r the runnable that has completed
     * @param t the exception that caused termination, or null if
     */
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if (t == null && r instanceof Future<?>) {
            try {
                ((Future<?>) r).get();
            } catch (CancellationException ce) {
                t = ce;
            } catch (ExecutionException ee) {
                t = ee.getCause();
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt(); // ignore/reset
            }
        }
        if (t != null) {
            ARouter.logger.warning(Consts.TAG, "Running task appeared exception! Thread [" + Thread.currentThread().getName() + "], because [" + t.getMessage() + "]\n" + TextUtils.formatStackTrace(t.getStackTrace()));
        }
    }
}


================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/thread/DefaultThreadFactory.java
================================================
package com.alibaba.android.arouter.thread;

import android.support.annotation.NonNull;

import com.alibaba.android.arouter.launcher.ARouter;
import com.alibaba.android.arouter.utils.Consts;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程池工厂类
 *
 * @author zhilong <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 15/12/25 上午10:51
 */
public class DefaultThreadFactory implements ThreadFactory {
    private static final AtomicInteger poolNumber = new AtomicInteger(1);

    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final String namePrefix;

    public DefaultThreadFactory() {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                Thread.currentThread().getThreadGroup();
        namePrefix = "ARouter task pool No." + poolNumber.getAndIncrement() + ", thread No.";
    }

    public Thread newThread(@NonNull Runnable runnable) {
        String threadName = namePrefix + threadNumber.getAndIncrement();
        ARouter.logger.info(Consts.TAG, "Thread production, name is [" + threadName + "]");
        Thread thread = new Thread(group, runnable, threadName, 0);
        if (thread.isDaemon()) {   //设为非后台线程
            thread.setDaemon(false);
        }
        if (thread.getPriority() != Thread.NORM_PRIORITY) { //优先级为normal
            thread.setPriority(Thread.NORM_PRIORITY);
        }

        // 捕获多线程处理中的异常
        thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable ex) {
                ARouter.logger.info(Consts.TAG, "Running task appeared exception! Thread [" + thread.getName() + "], because [" + ex.getMessage() + "]");
            }
        });
        return thread;
    }
}

================================================
FILE: arouter-api/src/main/java/com/alibaba/android/arouter/utils/ClassUtils.java
================================================
package com.alibaba.android.arouter.utils;

// Copy from galaxy sdk ${com.alibaba.android.galaxy.utils.ClassUtils}

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;

import com.alibaba.android.arouter.launcher.ARouter;
import com.alibaba.android.arouter.thread.DefaultPoolExecutor;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import dalvik.system.DexFile;

/**
 * Scanner, find out class with any conditions, copy from google source code.
 *
 * @author 正纬 <a href="mailto:zhilong.liu@aliyun.com">Contact me.</a>
 * @version 1.0
 * @since 16/6/27 下午10:58
 */
public class ClassUtils {
    private static final String EXTRACTED_NAME_EXT = ".classes";
    private static final String EXTRACTED_SUFFIX = ".zip";

    private static final String SECONDARY_FOLDER_NAME = "code_cache" + File.separator + "secondary-dexes";

    private static final String PREFS_FILE = "multidex.version";
    private static final String KEY_DEX_NUMBER = "dex.number";

    private static final int VM_WITH_MULTIDEX_VERSION_MAJOR = 2;
    private static final int VM_WITH_MULTIDEX_VERSION_MINOR = 1;

    private static SharedPreferences getMultiDexPreferences(Context context) {
        return context.getSharedPreferences(PREFS_FILE, Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? Context.MODE_PRIVATE : Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
    }

    /**
     * 通过指定包名,扫描包下面包含的所有的ClassName
     *
     * @param context     U know
     * @param packageName 包名
     * @return 所有class的集合
     */
    public static Set<String> getFileNameByPackageName(Context context, final String packageName) throws PackageManager.NameNotFoundException, IOException, InterruptedException {
        final Set<String> classNames = new HashSet<>();

        List<String> paths = getSourcePaths(context);
        final CountDownLatch parserCtl = new CountDownLatch(paths.size());

        for (final String path : paths) {
            DefaultPoolExecutor.getInstance().execute(new Runnable() {
                @Override
                public void run() {
                    DexFile dexfile = null;

                    try {
                        if (path.endsWith(EXTRACTED_SUFFIX)) {
                            //NOT use new DexFile(path), because it will throw "permission error in /data/dalvik-cache"
                            dexfile = DexFile.loadDex(path, path + ".tmp", 0);
                        } else {
                            dexfile = new DexFile(path);
                        }

                        Enumeration<String> dexEntries = dexfile.entries();
                        while (dexEntries.hasMoreElements()) {
                            String className = dexEntries.nextElement();
                            if (className.startsWith(packageName)) {
                                classNames.add(className);
                            }
                        }
                    } catch (Throwable
Download .txt
gitextract_0558mpl4/

├── .github/
│   ├── ISSUE_TEMPLATE.md
│   └── workflows/
│       └── gradle-wrapper-validation.yml
├── .gitignore
├── LICENSE
├── README.md
├── README_CN.md
├── app/
│   ├── build.gradle
│   ├── doc/
│   │   └── debug/
│   │       └── debug.keystore
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── assets/
│           │   └── scheme-test.html
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── demo/
│           │                       ├── MainActivity.java
│           │                       └── SchemeFilterActivity.java
│           └── res/
│               ├── anim/
│               │   ├── slide_in_bottom.xml
│               │   └── slide_out_bottom.xml
│               ├── drawable/
│               │   └── bg_test_area.xml
│               ├── layout/
│               │   └── activity_main.xml
│               └── values/
│                   ├── color.xml
│                   ├── dimens.xml
│                   └── strings.xml
├── arouter-annotation/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── android/
│                           └── arouter/
│                               └── facade/
│                                   ├── annotation/
│                                   │   ├── Autowired.java
│                                   │   ├── Interceptor.java
│                                   │   ├── Param.java
│                                   │   └── Route.java
│                                   ├── enums/
│                                   │   ├── RouteType.java
│                                   │   └── TypeKind.java
│                                   └── model/
│                                       ├── RouteMeta.java
│                                       └── TypeWrapper.java
├── arouter-api/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── android/
│                           └── arouter/
│                               ├── base/
│                               │   └── UniqueKeyTreeMap.java
│                               ├── core/
│                               │   ├── AutowiredLifecycleCallback.java
│                               │   ├── AutowiredServiceImpl.java
│                               │   ├── InstrumentationHook.java
│                               │   ├── InterceptorServiceImpl.java
│                               │   ├── LogisticsCenter.java
│                               │   └── Warehouse.java
│                               ├── exception/
│                               │   ├── HandlerException.java
│                               │   ├── InitException.java
│                               │   └── NoRouteFoundException.java
│                               ├── facade/
│                               │   ├── Postcard.java
│                               │   ├── callback/
│                               │   │   ├── InterceptorCallback.java
│                               │   │   ├── NavCallback.java
│                               │   │   └── NavigationCallback.java
│                               │   ├── service/
│                               │   │   ├── AutowiredService.java
│                               │   │   ├── ClassLoaderService.java
│                               │   │   ├── DegradeService.java
│                               │   │   ├── InterceptorService.java
│                               │   │   ├── PathReplaceService.java
│                               │   │   ├── PretreatmentService.java
│                               │   │   └── SerializationService.java
│                               │   └── template/
│                               │       ├── IInterceptor.java
│                               │       ├── IInterceptorGroup.java
│                               │       ├── ILogger.java
│                               │       ├── IPolicy.java
│                               │       ├── IProvider.java
│                               │       ├── IProviderGroup.java
│                               │       ├── IRouteGroup.java
│                               │       ├── IRouteRoot.java
│                               │       └── ISyringe.java
│                               ├── launcher/
│                               │   ├── ARouter.java
│                               │   └── _ARouter.java
│                               ├── thread/
│                               │   ├── CancelableCountDownLatch.java
│                               │   ├── DefaultPoolExecutor.java
│                               │   └── DefaultThreadFactory.java
│                               └── utils/
│                                   ├── ClassUtils.java
│                                   ├── Consts.java
│                                   ├── DefaultLogger.java
│                                   ├── MapUtils.java
│                                   ├── PackageUtils.java
│                                   └── TextUtils.java
├── arouter-compiler/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── compiler/
│           │                       ├── entity/
│           │                       │   └── RouteDoc.java
│           │                       ├── processor/
│           │                       │   ├── AutowiredProcessor.java
│           │                       │   ├── BaseProcessor.java
│           │                       │   ├── InterceptorProcessor.java
│           │                       │   └── RouteProcessor.java
│           │                       └── utils/
│           │                           ├── Consts.java
│           │                           ├── Logger.java
│           │                           └── TypeUtils.java
│           └── resources/
│               └── META-INF/
│                   └── gradle/
│                       └── incremental.annotation.processors
├── arouter-gradle-plugin/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           ├── groovy/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── register/
│           │                       ├── core/
│           │                       │   ├── RegisterCodeGenerator.groovy
│           │                       │   └── RegisterTransform.groovy
│           │                       ├── launch/
│           │                       │   └── PluginLaunch.groovy
│           │                       └── utils/
│           │                           ├── Logger.groovy
│           │                           ├── ScanSetting.groovy
│           │                           └── ScanUtil.groovy
│           └── resources/
│               └── META-INF/
│                   └── gradle-plugins/
│                       └── com.alibaba.arouter.properties
├── arouter-idea-plugin/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── kotlin/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── idea/
│           │                       └── extensions/
│           │                           └── NavigationLineMarker.kt
│           └── resources/
│               └── META-INF/
│                   └── plugin.xml
├── build.gradle
├── demo/
│   ├── arouter-demo-1.5.2.apk
│   └── arouter-demo.apk
├── gradle/
│   ├── publish.gradle
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── module-java/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── demo/
│           │                       └── module1/
│           │                           ├── BlankFragment.java
│           │                           ├── MainLooper.java
│           │                           ├── TestInterceptor90.java
│           │                           ├── TestModule2Activity.java
│           │                           ├── TestModuleActivity.java
│           │                           ├── TestWebview.java
│           │                           ├── testactivity/
│           │                           │   ├── BaseActivity.java
│           │                           │   ├── Test1Activity.java
│           │                           │   ├── Test2Activity.java
│           │                           │   ├── Test3Activity.java
│           │                           │   ├── Test4Activity.java
│           │                           │   └── TestDynamicActivity.java
│           │                           ├── testinterceptor/
│           │                           │   └── Test1Interceptor.java
│           │                           └── testservice/
│           │                               ├── HelloServiceImpl.java
│           │                               ├── JsonServiceImpl.java
│           │                               └── SingleService.java
│           └── res/
│               ├── layout/
│               │   ├── activity_test1.xml
│               │   ├── activity_test2.xml
│               │   ├── activity_test4.xml
│               │   ├── activity_test_module.xml
│               │   ├── activity_test_module2.xml
│               │   └── activity_test_webview.xml
│               └── values/
│                   ├── dimens.xml
│                   └── strings.xml
├── module-java-export/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── alibaba/
│                       └── android/
│                           └── arouter/
│                               └── demo/
│                                   └── service/
│                                       ├── Entrance.java
│                                       ├── HelloService.java
│                                       └── model/
│                                           ├── TestObj.java
│                                           ├── TestParcelable.java
│                                           └── TestSerializable.java
├── module-kotlin/
│   ├── build.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── alibaba/
│           │           └── android/
│           │               └── arouter/
│           │                   └── demo/
│           │                       └── kotlin/
│           │                           ├── KotlinTestActivity.kt
│           │                           └── TestNormalActivity.java
│           └── res/
│               ├── layout/
│               │   ├── activity_kotlin_test.xml
│               │   └── activity_test_normal.xml
│               └── values/
│                   ├── dimens.xml
│                   └── strings.xml
└── settings.gradle
Download .txt
SYMBOL INDEX (426 symbols across 77 files)

FILE: app/src/main/java/com/alibaba/android/arouter/demo/MainActivity.java
  class MainActivity (line 32) | public class MainActivity extends AppCompatActivity implements View.OnCl...
    method onCreate (line 33) | @Override
    method onClick (line 44) | @Override
    method onActivityResult (line 252) | @Override

FILE: app/src/main/java/com/alibaba/android/arouter/demo/SchemeFilterActivity.java
  class SchemeFilterActivity (line 11) | public class SchemeFilterActivity extends Activity {
    method onCreate (line 13) | @Override

FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/RouteType.java
  type RouteType (line 10) | public enum RouteType {
    method getId (line 23) | public int getId() {
    method setId (line 27) | public RouteType setId(int id) {
    method getClassName (line 32) | public String getClassName() {
    method setClassName (line 36) | public RouteType setClassName(String className) {
    method RouteType (line 41) | RouteType(int id, String className) {
    method parse (line 46) | public static RouteType parse(String name) {

FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/TypeKind.java
  type TypeKind (line 10) | public enum TypeKind {

FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/RouteMeta.java
  class RouteMeta (line 18) | public class RouteMeta {
    method RouteMeta (line 31) | public RouteMeta() {
    method build (line 45) | public static RouteMeta build(RouteType type, Class<?> destination, St...
    method build (line 61) | public static RouteMeta build(RouteType type, Class<?> destination, St...
    method RouteMeta (line 72) | public RouteMeta(Route route, Class<?> destination, RouteType type) {
    method RouteMeta (line 84) | public RouteMeta(Route route, Element rawType, RouteType type, Map<Str...
    method RouteMeta (line 100) | public RouteMeta(RouteType type, Element rawType, Class<?> destination...
    method getParamsType (line 112) | public Map<String, Integer> getParamsType() {
    method setParamsType (line 116) | public RouteMeta setParamsType(Map<String, Integer> paramsType) {
    method getInjectConfig (line 121) | public Map<String, Autowired> getInjectConfig() {
    method setInjectConfig (line 125) | public void setInjectConfig(Map<String, Autowired> injectConfig) {
    method getRawType (line 129) | public Element getRawType() {
    method setRawType (line 133) | public RouteMeta setRawType(Element rawType) {
    method getType (line 138) | public RouteType getType() {
    method setType (line 142) | public RouteMeta setType(RouteType type) {
    method getDestination (line 147) | public Class<?> getDestination() {
    method setDestination (line 151) | public RouteMeta setDestination(Class<?> destination) {
    method getPath (line 156) | public String getPath() {
    method setPath (line 160) | public RouteMeta setPath(String path) {
    method getGroup (line 165) | public String getGroup() {
    method setGroup (line 169) | public RouteMeta setGroup(String group) {
    method getPriority (line 174) | public int getPriority() {
    method setPriority (line 178) | public RouteMeta setPriority(int priority) {
    method getExtra (line 183) | public int getExtra() {
    method setExtra (line 187) | public RouteMeta setExtra(int extra) {
    method getName (line 192) | public String getName() {
    method setName (line 196) | public void setName(String name) {
    method toString (line 200) | @Override

FILE: arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/TypeWrapper.java
  class TypeWrapper (line 13) | public class TypeWrapper<T> {
    method TypeWrapper (line 16) | protected TypeWrapper() {
    method getType (line 22) | public Type getType() {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/base/UniqueKeyTreeMap.java
  class UniqueKeyTreeMap (line 12) | public class UniqueKeyTreeMap<K, V> extends TreeMap<K, V> {
    method UniqueKeyTreeMap (line 15) | public UniqueKeyTreeMap(String exceptionText) {
    method put (line 21) | @Override

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/AutowiredLifecycleCallback.java
  class AutowiredLifecycleCallback (line 18) | @Deprecated
    method onActivityCreated (line 21) | @Override
    method onActivityStarted (line 26) | @Override
    method onActivityResumed (line 31) | @Override
    method onActivityPaused (line 36) | @Override
    method onActivityStopped (line 41) | @Override
    method onActivitySaveInstanceState (line 46) | @Override
    method onActivityDestroyed (line 51) | @Override

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/AutowiredServiceImpl.java
  class AutowiredServiceImpl (line 22) | @Route(path = "/arouter/service/autowired")
    method init (line 27) | @Override
    method autowire (line 33) | @Override
    method doInject (line 44) | private void doInject(Object instance, Class<?> parent) {
    method getSyringe (line 59) | private ISyringe getSyringe(Class<?> clazz) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/InstrumentationHook.java
  class InstrumentationHook (line 24) | @Deprecated
    method newActivity (line 39) | public Activity newActivity(ClassLoader cl, String className,

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/InterceptorServiceImpl.java
  class InterceptorServiceImpl (line 27) | @Route(path = "/arouter/service/interceptor")
    method doInterceptions (line 32) | @Override
    method _execute (line 74) | private static void _execute(final int index, final CancelableCountDow...
    method init (line 102) | @Override
    method checkInterceptorsInitStatus (line 131) | private static void checkInterceptorsInitStatus() {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java
  class LogisticsCenter (line 53) | public class LogisticsCenter {
    method loadRouterMap (line 62) | private static void loadRouterMap() {
    method register (line 75) | private static void register(String className) {
    method registerRouteRoot (line 100) | private static void registerRouteRoot(IRouteRoot routeRoot) {
    method registerInterceptor (line 111) | private static void registerInterceptor(IInterceptorGroup interceptorG...
    method registerProvider (line 122) | private static void registerProvider(IProviderGroup providerGroup) {
    method markRegisteredByPlugin (line 132) | private static void markRegisteredByPlugin() {
    method init (line 141) | public synchronized static void init(Context context, ThreadPoolExecut...
    method buildProvider (line 206) | public static Postcard buildProvider(String serviceName) {
    method completion (line 221) | public synchronized static void completion(Postcard postcard) {
    method setValue (line 313) | private static void setValue(Postcard postcard, Integer typeDef, Strin...
    method suspend (line 354) | public static void suspend() {
    method addRouteGroupDynamic (line 358) | public synchronized static void addRouteGroupDynamic(String groupName,...

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/core/Warehouse.java
  class Warehouse (line 21) | class Warehouse {
    method clear (line 34) | static void clear() {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/exception/HandlerException.java
  class HandlerException (line 10) | public class HandlerException extends RuntimeException {
    method HandlerException (line 11) | public HandlerException(String detailMessage) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/exception/InitException.java
  class InitException (line 10) | public class InitException extends RuntimeException {
    method InitException (line 11) | public InitException(String detailMessage) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/exception/NoRouteFoundException.java
  class NoRouteFoundException (line 10) | public class NoRouteFoundException extends RuntimeException {
    method NoRouteFoundException (line 17) | public NoRouteFoundException(String detailMessage) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java
  class Postcard (line 30) | public final class Postcard extends RouteMeta {
    method getOptionsBundle (line 48) | public Bundle getOptionsBundle() {
    method getEnterAnim (line 52) | public int getEnterAnim() {
    method getExitAnim (line 56) | public int getExitAnim() {
    method getProvider (line 60) | public IProvider getProvider() {
    method setProvider (line 64) | public Postcard setProvider(IProvider provider) {
    method Postcard (line 69) | public Postcard() {
    method Postcard (line 73) | public Postcard(String path, String group) {
    method Postcard (line 77) | public Postcard(String path, String group, Uri uri, Bundle bundle) {
    method isGreenChannel (line 84) | public boolean isGreenChannel() {
    method getTag (line 88) | public Object getTag() {
    method setTag (line 92) | public Postcard setTag(Object tag) {
    method getExtras (line 97) | public Bundle getExtras() {
    method getTimeout (line 101) | public int getTimeout() {
    method setTimeout (line 111) | public Postcard setTimeout(int timeout) {
    method getUri (line 116) | public Uri getUri() {
    method setUri (line 120) | public Postcard setUri(Uri uri) {
    method navigation (line 129) | public Object navigation() {
    method navigation (line 138) | public Object navigation(Context context) {
    method navigation (line 147) | public Object navigation(Context context, NavigationCallback callback) {
    method navigation (line 157) | public void navigation(Activity mContext, int requestCode) {
    method navigation (line 167) | public void navigation(Activity mContext, int requestCode, NavigationC...
    method greenChannel (line 176) | public Postcard greenChannel() {
    method with (line 184) | public Postcard with(Bundle bundle) {
    method withFlags (line 200) | public Postcard withFlags(int flag) {
    method addFlags (line 214) | public Postcard addFlags(int flags) {
    method getFlags (line 219) | public int getFlags() {
    method withObject (line 230) | public Postcard withObject(@Nullable String key, @Nullable Object valu...
    method withString (line 246) | public Postcard withString(@Nullable String key, @Nullable String valu...
    method withBoolean (line 259) | public Postcard withBoolean(@Nullable String key, boolean value) {
    method withShort (line 272) | public Postcard withShort(@Nullable String key, short value) {
    method withInt (line 285) | public Postcard withInt(@Nullable String key, int value) {
    method withLong (line 298) | public Postcard withLong(@Nullable String key, long value) {
    method withDouble (line 311) | public Postcard withDouble(@Nullable String key, double value) {
    method withByte (line 324) | public Postcard withByte(@Nullable String key, byte value) {
    method withChar (line 337) | public Postcard withChar(@Nullable String key, char value) {
    method withFloat (line 350) | public Postcard withFloat(@Nullable String key, float value) {
    method withCharSequence (line 363) | public Postcard withCharSequence(@Nullable String key, @Nullable CharS...
    method withParcelable (line 376) | public Postcard withParcelable(@Nullable String key, @Nullable Parcela...
    method withParcelableArray (line 390) | public Postcard withParcelableArray(@Nullable String key, @Nullable Pa...
    method withParcelableArrayList (line 404) | public Postcard withParcelableArrayList(@Nullable String key, @Nullabl...
    method withSparseParcelableArray (line 418) | public Postcard withSparseParcelableArray(@Nullable String key, @Nulla...
    method withIntegerArrayList (line 431) | public Postcard withIntegerArrayList(@Nullable String key, @Nullable A...
    method withStringArrayList (line 444) | public Postcard withStringArrayList(@Nullable String key, @Nullable Ar...
    method withCharSequenceArrayList (line 457) | public Postcard withCharSequenceArrayList(@Nullable String key, @Nulla...
    method withSerializable (line 470) | public Postcard withSerializable(@Nullable String key, @Nullable Seria...
    method withByteArray (line 483) | public Postcard withByteArray(@Nullable String key, @Nullable byte[] v...
    method withShortArray (line 496) | public Postcard withShortArray(@Nullable String key, @Nullable short[]...
    method withCharArray (line 509) | public Postcard withCharArray(@Nullable String key, @Nullable char[] v...
    method withFloatArray (line 522) | public Postcard withFloatArray(@Nullable String key, @Nullable float[]...
    method withCharSequenceArray (line 535) | public Postcard withCharSequenceArray(@Nullable String key, @Nullable ...
    method withBundle (line 548) | public Postcard withBundle(@Nullable String key, @Nullable Bundle valu...
    method withTransition (line 560) | public Postcard withTransition(int enterAnim, int exitAnim) {
    method withOptionsCompat (line 572) | @RequiresApi(16)
    method toString (line 580) | @Override
    method getAction (line 597) | public String getAction() {
    method withAction (line 601) | public Postcard withAction(String action) {
    method getContext (line 606) | public Context getContext() {
    method setContext (line 610) | public void setContext(Context context) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/callback/InterceptorCallback.java
  type InterceptorCallback (line 12) | public interface InterceptorCallback {
    method onContinue (line 19) | void onContinue(Postcard postcard);
    method onInterrupt (line 26) | void onInterrupt(Throwable exception);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/callback/NavCallback.java
  class NavCallback (line 12) | public abstract class NavCallback implements NavigationCallback {
    method onFound (line 13) | @Override
    method onLost (line 18) | @Override
    method onArrival (line 23) | @Override
    method onInterrupt (line 26) | @Override

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/callback/NavigationCallback.java
  type NavigationCallback (line 12) | public interface NavigationCallback {
    method onFound (line 19) | void onFound(Postcard postcard);
    method onLost (line 26) | void onLost(Postcard postcard);
    method onArrival (line 33) | void onArrival(Postcard postcard);
    method onInterrupt (line 40) | void onInterrupt(Postcard postcard);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/AutowiredService.java
  type AutowiredService (line 12) | public interface AutowiredService extends IProvider {
    method autowire (line 18) | void autowire(Object instance);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/ClassLoaderService.java
  type ClassLoaderService (line 12) | public interface ClassLoaderService extends IProvider {
    method forName (line 13) | Class<?> forName();

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/DegradeService.java
  type DegradeService (line 15) | public interface DegradeService extends IProvider {
    method onLost (line 22) | void onLost(Context context, Postcard postcard);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/InterceptorService.java
  type InterceptorService (line 14) | public interface InterceptorService extends IProvider {
    method doInterceptions (line 19) | void doInterceptions(Postcard postcard, InterceptorCallback callback);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/PathReplaceService.java
  type PathReplaceService (line 14) | public interface PathReplaceService extends IProvider {
    method forString (line 21) | String forString(String path);
    method forUri (line 28) | Uri forUri(Uri uri);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/PretreatmentService.java
  type PretreatmentService (line 14) | public interface PretreatmentService extends IProvider {
    method onPretreatment (line 22) | boolean onPretreatment(Context context, Postcard postcard);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/SerializationService.java
  type SerializationService (line 14) | public interface SerializationService extends IProvider {
    method json2Object (line 25) | @Deprecated
    method object2Json (line 34) | String object2Json(Object instance);
    method parseObject (line 43) | <T> T parseObject(String input, Type clazz);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IInterceptor.java
  type IInterceptor (line 13) | public interface IInterceptor extends IProvider {
    method process (line 21) | void process(Postcard postcard, InterceptorCallback callback);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IInterceptorGroup.java
  type IInterceptorGroup (line 12) | public interface IInterceptorGroup {
    method loadInto (line 18) | void loadInto(Map<Integer, Class<? extends IInterceptor>> interceptor);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/ILogger.java
  type ILogger (line 12) | public interface ILogger {
    method showLog (line 18) | void showLog(boolean isShowLog);
    method showStackTrace (line 20) | void showStackTrace(boolean isShowStackTrace);
    method debug (line 22) | void debug(String tag, String message);
    method info (line 24) | void info(String tag, String message);
    method warning (line 26) | void warning(String tag, String message);
    method error (line 28) | void error(String tag, String message);
    method error (line 30) | void error(String tag, String message, Throwable e);
    method monitor (line 32) | void monitor(String message);
    method isMonitorMode (line 34) | boolean isMonitorMode();
    method getDefaultTag (line 36) | String getDefaultTag();

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IPolicy.java
  type IPolicy (line 10) | @Deprecated
    method getFlag (line 12) | int getFlag();

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IProvider.java
  type IProvider (line 12) | public interface IProvider {
    method init (line 19) | void init(Context context);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IProviderGroup.java
  type IProviderGroup (line 14) | public interface IProviderGroup {
    method loadInto (line 20) | void loadInto(Map<String, RouteMeta> providers);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IRouteGroup.java
  type IRouteGroup (line 14) | public interface IRouteGroup {
    method loadInto (line 18) | void loadInto(Map<String, RouteMeta> atlas);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IRouteRoot.java
  type IRouteRoot (line 12) | public interface IRouteRoot {
    method loadInto (line 18) | void loadInto(Map<String, Class<? extends IRouteGroup>> routes);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/ISyringe.java
  type ISyringe (line 10) | public interface ISyringe {
    method inject (line 11) | void inject(Object target);

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/launcher/ARouter.java
  class ARouter (line 24) | public final class ARouter {
    method ARouter (line 33) | private ARouter() {
    method init (line 39) | public static void init(Application application) {
    method getInstance (line 57) | public static ARouter getInstance() {
    method openDebug (line 72) | public static synchronized void openDebug() {
    method debuggable (line 76) | public static boolean debuggable() {
    method openLog (line 80) | public static synchronized void openLog() {
    method printStackTrace (line 84) | public static synchronized void printStackTrace() {
    method setExecutor (line 88) | public static synchronized void setExecutor(ThreadPoolExecutor tpe) {
    method destroy (line 92) | public synchronized void destroy() {
    method enableAutoInject (line 100) | @Deprecated
    method canAutoInject (line 105) | @Deprecated
    method attachBaseContext (line 113) | @Deprecated
    method monitorMode (line 118) | public static synchronized void monitorMode() {
    method isMonitorMode (line 122) | public static boolean isMonitorMode() {
    method setLogger (line 126) | public static void setLogger(ILogger userLogger) {
    method inject (line 133) | public void inject(Object thiz) {
    method build (line 142) | public Postcard build(String path) {
    method build (line 152) | @Deprecated
    method build (line 162) | public Postcard build(Uri url) {
    method navigation (line 173) | public <T> T navigation(Class<? extends T> service) {
    method navigation (line 185) | public Object navigation(Context mContext, Postcard postcard, int requ...
    method addRouteGroup (line 194) | public boolean addRouteGroup(IRouteGroup group) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/launcher/_ARouter.java
  class _ARouter (line 45) | final class _ARouter {
    method _ARouter (line 58) | private _ARouter() {
    method init (line 61) | protected static synchronized boolean init(Application application) {
    method destroy (line 74) | static synchronized void destroy() {
    method getInstance (line 84) | protected static _ARouter getInstance() {
    method openDebug (line 99) | static synchronized void openDebug() {
    method openLog (line 104) | static synchronized void openLog() {
    method enableAutoInject (line 109) | @Deprecated
    method canAutoInject (line 114) | @Deprecated
    method attachBaseContext (line 119) | @Deprecated
    method printStackTrace (line 142) | static synchronized void printStackTrace() {
    method setExecutor (line 147) | static synchronized void setExecutor(ThreadPoolExecutor tpe) {
    method monitorMode (line 151) | static synchronized void monitorMode() {
    method isMonitorMode (line 156) | static boolean isMonitorMode() {
    method debuggable (line 160) | static boolean debuggable() {
    method setLogger (line 164) | static void setLogger(ILogger userLogger) {
    method inject (line 170) | static void inject(Object thiz) {
    method build (line 180) | protected Postcard build(String path) {
    method build (line 195) | protected Postcard build(Uri uri) {
    method build (line 210) | protected Postcard build(String path, String group, Boolean afterRepla...
    method extractGroup (line 227) | private String extractGroup(String path) {
    method afterInit (line 245) | static void afterInit() {
    method navigation (line 250) | protected <T> T navigation(Class<? extends T> service) {
    method navigation (line 284) | protected Object navigation(final Context context, final Postcard post...
    method _navigation (line 361) | private Object _navigation(final Postcard postcard, final int requestC...
    method runInMainThread (line 428) | private void runInMainThread(Runnable runnable) {
    method startActivity (line 441) | private void startActivity(int requestCode, Context currentContext, In...
    method addRouteGroup (line 461) | boolean addRouteGroup(IRouteGroup group) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/thread/CancelableCountDownLatch.java
  class CancelableCountDownLatch (line 12) | public class CancelableCountDownLatch extends CountDownLatch {
    method CancelableCountDownLatch (line 20) | public CancelableCountDownLatch(int count) {
    method cancel (line 24) | public void cancel() {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/thread/DefaultPoolExecutor.java
  class DefaultPoolExecutor (line 24) | public class DefaultPoolExecutor extends ThreadPoolExecutor {
    method getInstance (line 33) | public static DefaultPoolExecutor getInstance() {
    method DefaultPoolExecutor (line 50) | private DefaultPoolExecutor(int corePoolSize, int maximumPoolSize, lon...
    method afterExecute (line 65) | @Override

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/thread/DefaultThreadFactory.java
  class DefaultThreadFactory (line 18) | public class DefaultThreadFactory implements ThreadFactory {
    method DefaultThreadFactory (line 25) | public DefaultThreadFactory() {
    method newThread (line 32) | public Thread newThread(@NonNull Runnable runnable) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/utils/ClassUtils.java
  class ClassUtils (line 37) | public class ClassUtils {
    method getMultiDexPreferences (line 49) | private static SharedPreferences getMultiDexPreferences(Context contex...
    method getFileNameByPackageName (line 60) | public static Set<String> getFileNameByPackageName(Context context, fi...
    method getSourcePaths (line 117) | public static List<String> getSourcePaths(Context context) throws Pack...
    method tryLoadInstantRunDexFile (line 156) | private static List<String> tryLoadInstantRunDexFile(ApplicationInfo a...
    method isVMMultidexCapable (line 195) | private static boolean isVMMultidexCapable() {
    method isYunOS (line 232) | private static boolean isYunOS() {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/utils/Consts.java
  class Consts (line 10) | public final class Consts {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/utils/DefaultLogger.java
  class DefaultLogger (line 15) | public class DefaultLogger implements ILogger {
    method showLog (line 23) | public void showLog(boolean showLog) {
    method showStackTrace (line 27) | public void showStackTrace(boolean showStackTrace) {
    method showMonitor (line 31) | public void showMonitor(boolean showMonitor) {
    method DefaultLogger (line 35) | public DefaultLogger() {
    method DefaultLogger (line 38) | public DefaultLogger(String defaultTag) {
    method debug (line 42) | @Override
    method info (line 50) | @Override
    method warning (line 58) | @Override
    method error (line 66) | @Override
    method error (line 74) | @Override
    method monitor (line 82) | @Override
    method isMonitorMode (line 90) | @Override
    method getDefaultTag (line 95) | @Override
    method getExtInfo (line 100) | public static String getExtInfo(StackTraceElement stackTraceElement) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/utils/MapUtils.java
  class MapUtils (line 12) | public class MapUtils {
    method isNotEmpty (line 22) | public static boolean isNotEmpty(final Map<?,?> map) {
    method isEmpty (line 35) | public static boolean isEmpty(final Map<?,?> map) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/utils/PackageUtils.java
  class PackageUtils (line 20) | public class PackageUtils {
    method isNewVersion (line 24) | public static boolean isNewVersion(Context context) {
    method updateVersion (line 45) | public static void updateVersion(Context context) {
    method getPackageInfo (line 52) | private static PackageInfo getPackageInfo(Context context) {

FILE: arouter-api/src/main/java/com/alibaba/android/arouter/utils/TextUtils.java
  class TextUtils (line 16) | public class TextUtils {
    method isEmpty (line 18) | public static boolean isEmpty(final CharSequence cs) {
    method formatStackTrace (line 25) | public static String formatStackTrace(StackTraceElement[] stackTrace) {
    method splitQueryParameters (line 39) | public static Map<String, String> splitQueryParameters(Uri rawUri) {
    method getLeft (line 77) | public static String getLeft(String key) {
    method getRight (line 91) | public static String getRight(String key) {

FILE: arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/entity/RouteDoc.java
  class RouteDoc (line 16) | public class RouteDoc {
    method getGroup (line 34) | public String getGroup() {
    method setGroup (line 38) | public void setGroup(String group) {
    method getPath (line 42) | public String getPath() {
    method setPath (line 46) | public void setPath(String path) {
    method getPrototype (line 50) | public String getPrototype() {
    method setPrototype (line 54) | public void setPrototype(String prototype) {
    method addPrototype (line 58) | public void addPrototype(String prototype) {
    method getClassName (line 66) | public String getClassName() {
    method setClassName (line 70) | public void setClassName(String className) {
    method getDescription (line 74) | public String getDescription() {
    method setDescription (line 78) | public void setDescription(String description) {
    method getType (line 84) | public String getType() {
    method setType (line 88) | public void setType(String type) {
    method getMark (line 92) | public int getMark() {
    method setMark (line 96) | public void setMark(int mark) {
    method getParams (line 100) | public List<Param> getParams() {
    method setParams (line 104) | public void setParams(List<Param> params) {
    class Param (line 108) | public static class Param {
      method getKey (line 118) | public String getKey() {
      method setKey (line 122) | public void setKey(String key) {
      method getType (line 126) | public String getType() {
      method setType (line 130) | public void setType(String type) {
      method getDescription (line 134) | public String getDescription() {
      method setDescription (line 138) | public void setDescription(String description) {
      method isRequired (line 144) | public boolean isRequired() {
      method setRequired (line 148) | public void setRequired(boolean required) {

FILE: arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/AutowiredProcessor.java
  class AutowiredProcessor (line 50) | @AutoService(Processor.class)
    method init (line 57) | @Override
    method process (line 64) | @Override
    method generateHelper (line 81) | private void generateHelper() throws IOException, IllegalAccessExcepti...
    method isKtClass (line 201) | private boolean isKtClass(Element element) {
    method buildCastCode (line 211) | private String buildCastCode(Element element) {
    method buildStatement (line 221) | private String buildStatement(String originalValue, String statement, ...
    method categories (line 269) | private void categories(Set<? extends Element> elements) throws Illega...

FILE: arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/BaseProcessor.java
  class BaseProcessor (line 28) | public abstract class BaseProcessor extends AbstractProcessor {
    method init (line 39) | @Override
    method getSupportedSourceVersion (line 66) | @Override
    method getSupportedOptions (line 71) | @Override

FILE: arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/InterceptorProcessor.java
  class InterceptorProcessor (line 43) | @AutoService(Processor.class)
    method init (line 49) | @Override
    method process (line 64) | @Override
    method parseInterceptors (line 84) | private void parseInterceptors(Set<? extends Element> elements) throws...
    method verify (line 165) | private boolean verify(Element element) {

FILE: arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java
  class RouteProcessor (line 71) | @AutoService(Processor.class)
    method init (line 80) | @Override
    method process (line 107) | @Override
    method parseRoutes (line 124) | private void parseRoutes(Set<? extends Element> routeElements) throws ...
    method injectParamCollector (line 377) | private void injectParamCollector(Element element, Map<String, Integer...
    method extractDocInfo (line 404) | private RouteDoc extractDocInfo(RouteMeta routeMeta) {
    method categories (line 420) | private void categories(RouteMeta routeMete) {
    method routeVerify (line 451) | private boolean routeVerify(RouteMeta meta) {

FILE: arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/Consts.java
  class Consts (line 10) | public class Consts {

FILE: arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/Logger.java
  class Logger (line 15) | public class Logger {
    method Logger (line 18) | public Logger(Messager messager) {
    method info (line 25) | public void info(CharSequence info) {
    method error (line 31) | public void error(CharSequence error) {
    method error (line 37) | public void error(Throwable error) {
    method warning (line 43) | public void warning(CharSequence warning) {
    method formatStackTrace (line 49) | private String formatStackTrace(StackTraceElement[] stackTrace) {

FILE: arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/TypeUtils.java
  class TypeUtils (line 29) | public class TypeUtils {
    method TypeUtils (line 35) | public TypeUtils(Types types, Elements elements) {
    method typeExchange (line 48) | public int typeExchange(Element element) {

FILE: module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/Entrance.java
  class Entrance (line 7) | public class Entrance {
    method redirect2Test1Activity (line 15) | public static void redirect2Test1Activity(String name, int age, Contex...

FILE: module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/HelloService.java
  type HelloService (line 12) | public interface HelloService extends IProvider {
    method sayHello (line 13) | void sayHello(String name);

FILE: module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/model/TestObj.java
  class TestObj (line 10) | public class TestObj {
    method TestObj (line 14) | public TestObj() {
    method TestObj (line 17) | public TestObj(String name, int id) {

FILE: module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/model/TestParcelable.java
  class TestParcelable (line 13) | public class TestParcelable implements Parcelable {
    method TestParcelable (line 17) | public TestParcelable() {
    method TestParcelable (line 20) | public TestParcelable(String name, int id) {
    method TestParcelable (line 25) | protected TestParcelable(Parcel in) {
    method writeToParcel (line 30) | @Override
    method describeContents (line 36) | @Override
    method createFromParcel (line 42) | @Override
    method newArray (line 47) | @Override

FILE: module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/model/TestSerializable.java
  class TestSerializable (line 8) | public class TestSerializable implements Serializable {
    method TestSerializable (line 12) | public TestSerializable() {
    method TestSerializable (line 15) | public TestSerializable(String name, int id) {

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/BlankFragment.java
  class BlankFragment (line 23) | @Route(path = "/test/fragment")
    method BlankFragment (line 62) | public BlankFragment() {
    method onCreateView (line 66) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/MainLooper.java
  class MainLooper (line 6) | public class MainLooper extends Handler {
    method MainLooper (line 9) | protected MainLooper(Looper looper) {
    method getInstance (line 13) | public static MainLooper getInstance() {
    method runOnUiThread (line 17) | public static void runOnUiThread(Runnable runnable) {

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/TestInterceptor90.java
  class TestInterceptor90 (line 18) | @Interceptor(priority = 90)
    method process (line 26) | @Override
    method init (line 36) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/TestModule2Activity.java
  class TestModule2Activity (line 8) | @Route(path = "/module/2", group = "m2")
    method onCreate (line 11) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/TestModuleActivity.java
  class TestModuleActivity (line 8) | @Route(path = "/module/1")
    method onCreate (line 11) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/TestWebview.java
  class TestWebview (line 9) | @Route(path = "/test/webview")
    method onCreate (line 14) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/BaseActivity.java
  class BaseActivity (line 10) | public class BaseActivity extends AppCompatActivity {

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/Test1Activity.java
  class Test1Activity (line 21) | @Route(path = "/test/activity1", name = "测试用 Activity")
    method onCreate (line 64) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/Test2Activity.java
  class Test2Activity (line 12) | @Route(path = "/test/activity2")
    method onCreate (line 18) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/Test3Activity.java
  class Test3Activity (line 15) | @Route(path = "/test/activity3")
    method onCreate (line 30) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/Test4Activity.java
  class Test4Activity (line 11) | @Route(path = "/test/activity4")
    method onCreate (line 14) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/TestDynamicActivity.java
  class TestDynamicActivity (line 7) | public class TestDynamicActivity extends Test1Activity {
    method onCreate (line 9) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testinterceptor/Test1Interceptor.java
  class Test1Interceptor (line 21) | @Interceptor(priority = 7)
    method process (line 29) | @Override
    method init (line 74) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testservice/HelloServiceImpl.java
  class HelloServiceImpl (line 17) | @Route(path = "/yourservicegroupname/hello")
    method sayHello (line 21) | @Override
    method init (line 31) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testservice/JsonServiceImpl.java
  class JsonServiceImpl (line 18) | @Route(path = "/yourservicegroupname/json")
    method init (line 20) | @Override
    method json2Object (line 25) | @Override
    method object2Json (line 30) | @Override
    method parseObject (line 35) | @Override

FILE: module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testservice/SingleService.java
  class SingleService (line 16) | @Route(path = "/yourservicegroupname/single")
    method sayHello (line 21) | public void sayHello(String name) {
    method init (line 25) | @Override

FILE: module-kotlin/src/main/java/com/alibaba/android/arouter/demo/kotlin/TestNormalActivity.java
  class TestNormalActivity (line 8) | @Route(path = "/kotlin/java")
    method onCreate (line 11) | @Override
Condensed preview — 148 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (364K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 368,
    "preview": "## Look at here\n\n- → Did you read the doc carefully\n- → Did you add annotation above target activity\n- → Did you add ann"
  },
  {
    "path": ".github/workflows/gradle-wrapper-validation.yml",
    "chars": 223,
    "preview": "name: \"Validate Gradle Wrapper\"\non: [push, pull_request]\n\njobs:\n  validation:\n    name: \"Validation\"\n    runs-on: ubuntu"
  },
  {
    "path": ".gitignore",
    "chars": 519,
    "preview": "# Built application files\n*.ap_\n\n# Files for the Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 19237,
    "preview": "```\n    A framework for assisting in the renovation of Android app componentization\n```\n\n[中文文档](https://github.com/aliba"
  },
  {
    "path": "README_CN.md",
    "chars": 18518,
    "preview": "```\n    一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦\n```\n\n[English](https://github.com/alibaba/ARouter/blob/master/RE"
  },
  {
    "path": "app/build.gradle",
    "chars": 1477,
    "preview": "apply plugin: 'com.android.application'\napply plugin: 'com.alibaba.arouter'\n\nandroid {\n    compileSdkVersion Integer.par"
  },
  {
    "path": "app/proguard-rules.pro",
    "chars": 2429,
    "preview": "-optimizationpasses 5\n-dontpreverify\n-dontwarn\n-ignorewarnings\n-verbose\n-overloadaggressively\n-dontusemixedcaseclassname"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "chars": 1719,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          pa"
  },
  {
    "path": "app/src/main/assets/scheme-test.html",
    "chars": 1261,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <title></title"
  },
  {
    "path": "app/src/main/java/com/alibaba/android/arouter/demo/MainActivity.java",
    "chars": 10937,
    "preview": "package com.alibaba.android.arouter.demo;\n\nimport android.content.Intent;\nimport android.net.Uri;\nimport android.os.Buil"
  },
  {
    "path": "app/src/main/java/com/alibaba/android/arouter/demo/SchemeFilterActivity.java",
    "chars": 748,
    "preview": "package com.alibaba.android.arouter.demo;\n\nimport android.app.Activity;\nimport android.net.Uri;\nimport android.os.Bundle"
  },
  {
    "path": "app/src/main/res/anim/slide_in_bottom.xml",
    "chars": 330,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <translate\n "
  },
  {
    "path": "app/src/main/res/anim/slide_out_bottom.xml",
    "chars": 332,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<set xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <translate\n "
  },
  {
    "path": "app/src/main/res/drawable/bg_test_area.xml",
    "chars": 225,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <stroke\n  "
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "chars": 11035,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:"
  },
  {
    "path": "app/src/main/res/values/color.xml",
    "chars": 101,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"red\">#f15533</color>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "chars": 304,
    "preview": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "chars": 25,
    "preview": "<resources>\n</resources>\n"
  },
  {
    "path": "arouter-annotation/build.gradle",
    "chars": 185,
    "preview": "apply plugin: 'java'\n\njava {\n    sourceCompatibility = JavaVersion.VERSION_1_8\n    targetCompatibility = JavaVersion.VER"
  },
  {
    "path": "arouter-annotation/gradle.properties",
    "chars": 151,
    "preview": "POM_NAME=ARouter Annotations\nPOM_ARTIFACT_ID=arouter-annotation\nPOM_PACKAGING=jar\nPOM_DESCRIPTION=The annotation used in"
  },
  {
    "path": "arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/annotation/Autowired.java",
    "chars": 764,
    "preview": "package com.alibaba.android.arouter.facade.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annota"
  },
  {
    "path": "arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/annotation/Interceptor.java",
    "chars": 814,
    "preview": "package com.alibaba.android.arouter.facade.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annota"
  },
  {
    "path": "arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/annotation/Param.java",
    "chars": 697,
    "preview": "package com.alibaba.android.arouter.facade.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annota"
  },
  {
    "path": "arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/annotation/Route.java",
    "chars": 1008,
    "preview": "package com.alibaba.android.arouter.facade.annotation;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annota"
  },
  {
    "path": "arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/RouteType.java",
    "chars": 1277,
    "preview": "package com.alibaba.android.arouter.facade.enums;\n\n/**\n * Type of route enum.\n *\n * @author Alex <a href=\"mailto:zhilong"
  },
  {
    "path": "arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/enums/TypeKind.java",
    "chars": 408,
    "preview": "package com.alibaba.android.arouter.facade.enums;\n\n/**\n * Kind of field type.\n *\n * @author Alex <a href=\"mailto:zhilong"
  },
  {
    "path": "arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/RouteMeta.java",
    "chars": 5959,
    "preview": "package com.alibaba.android.arouter.facade.model;\n\nimport com.alibaba.android.arouter.facade.annotation.Autowired;\nimpor"
  },
  {
    "path": "arouter-annotation/src/main/java/com/alibaba/android/arouter/facade/model/TypeWrapper.java",
    "chars": 588,
    "preview": "package com.alibaba.android.arouter.facade.model;\n\nimport java.lang.reflect.ParameterizedType;\nimport java.lang.reflect."
  },
  {
    "path": "arouter-api/build.gradle",
    "chars": 1003,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n    compileSdkVersion Integer.parseInt(COMPILE_SDK_VERSION)\n    buildTool"
  },
  {
    "path": "arouter-api/gradle.properties",
    "chars": 129,
    "preview": "POM_NAME=ARouter SDK\nPOM_ARTIFACT_ID=arouter-api\nPOM_PACKAGING=aar\nPOM_DESCRIPTION=Route framework for android\nVERSION_N"
  },
  {
    "path": "arouter-api/src/main/AndroidManifest.xml",
    "chars": 65,
    "preview": "<manifest\n    package=\"com.alibaba.android.arouter\">\n</manifest>\n"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/base/UniqueKeyTreeMap.java",
    "chars": 658,
    "preview": "package com.alibaba.android.arouter.base;\n\nimport java.util.TreeMap;\n\n/**\n * TreeMap with unique key.\n *\n * @author zhil"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/core/AutowiredLifecycleCallback.java",
    "chars": 1215,
    "preview": "package com.alibaba.android.arouter.core;\n\nimport android.annotation.TargetApi;\nimport android.app.Activity;\nimport andr"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/core/AutowiredServiceImpl.java",
    "chars": 2352,
    "preview": "package com.alibaba.android.arouter.core;\n\nimport android.content.Context;\nimport android.util.LruCache;\n\nimport com.ali"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/core/InstrumentationHook.java",
    "chars": 2677,
    "preview": "package com.alibaba.android.arouter.core;\n\nimport android.app.Activity;\nimport android.app.Instrumentation;\nimport andro"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/core/InterceptorServiceImpl.java",
    "chars": 6346,
    "preview": "package com.alibaba.android.arouter.core;\n\nimport android.content.Context;\n\nimport com.alibaba.android.arouter.exception"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java",
    "chars": 17019,
    "preview": "package com.alibaba.android.arouter.core;\n\nimport android.content.Context;\nimport android.net.Uri;\n\nimport com.alibaba.a"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/core/Warehouse.java",
    "chars": 1425,
    "preview": "package com.alibaba.android.arouter.core;\n\nimport com.alibaba.android.arouter.base.UniqueKeyTreeMap;\nimport com.alibaba."
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/exception/HandlerException.java",
    "chars": 335,
    "preview": "package com.alibaba.android.arouter.exception;\n\n/**\n * 主流程的处理异常\n *\n * @author zhilong <a href=\"mailto:zhilong.liu@aliyun"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/exception/InitException.java",
    "chars": 332,
    "preview": "package com.alibaba.android.arouter.exception;\n\n/**\n * 初始化相关异常\n *\n * @author zhilong <a href=\"mailto:zhilong.liu@aliyun."
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/exception/NoRouteFoundException.java",
    "chars": 552,
    "preview": "package com.alibaba.android.arouter.exception;\n\n/**\n * As its name\n *\n * @author Alex <a href=\"mailto:zhilong.liu@aliyun"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/Postcard.java",
    "chars": 18287,
    "preview": "package com.alibaba.android.arouter.facade;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/callback/InterceptorCallback.java",
    "chars": 611,
    "preview": "package com.alibaba.android.arouter.facade.callback;\n\nimport com.alibaba.android.arouter.facade.Postcard;\n\n/**\n * The ca"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/callback/NavCallback.java",
    "chars": 682,
    "preview": "package com.alibaba.android.arouter.facade.callback;\n\nimport com.alibaba.android.arouter.facade.Postcard;\n\n/**\n * Easy t"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/callback/NavigationCallback.java",
    "chars": 807,
    "preview": "package com.alibaba.android.arouter.facade.callback;\n\nimport com.alibaba.android.arouter.facade.Postcard;\n\n/**\n * Callba"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/AutowiredService.java",
    "chars": 464,
    "preview": "package com.alibaba.android.arouter.facade.service;\n\nimport com.alibaba.android.arouter.facade.template.IProvider;\n\n/**\n"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/ClassLoaderService.java",
    "chars": 420,
    "preview": "package com.alibaba.android.arouter.facade.service;\n\nimport com.alibaba.android.arouter.facade.template.IProvider;\n\n/**\n"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/DegradeService.java",
    "chars": 590,
    "preview": "package com.alibaba.android.arouter.facade.service;\n\nimport android.content.Context;\n\nimport com.alibaba.android.arouter"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/InterceptorService.java",
    "chars": 571,
    "preview": "package com.alibaba.android.arouter.facade.service;\n\nimport com.alibaba.android.arouter.facade.Postcard;\nimport com.alib"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/PathReplaceService.java",
    "chars": 555,
    "preview": "package com.alibaba.android.arouter.facade.service;\n\nimport android.net.Uri;\n\nimport com.alibaba.android.arouter.facade."
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/PretreatmentService.java",
    "chars": 656,
    "preview": "package com.alibaba.android.arouter.facade.service;\n\nimport android.content.Context;\nimport com.alibaba.android.arouter."
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/service/SerializationService.java",
    "chars": 970,
    "preview": "package com.alibaba.android.arouter.facade.service;\n\nimport com.alibaba.android.arouter.facade.template.IProvider;\n\nimpo"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IInterceptor.java",
    "chars": 590,
    "preview": "package com.alibaba.android.arouter.facade.template;\n\nimport com.alibaba.android.arouter.facade.Postcard;\nimport com.ali"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IInterceptorGroup.java",
    "chars": 437,
    "preview": "package com.alibaba.android.arouter.facade.template;\n\nimport java.util.Map;\n\n/**\n * Template of interceptor group.\n *\n *"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/ILogger.java",
    "chars": 794,
    "preview": "package com.alibaba.android.arouter.facade.template;\n\nimport com.alibaba.android.arouter.utils.Consts;\n\n/**\n * Logger\n *"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IPolicy.java",
    "chars": 254,
    "preview": "package com.alibaba.android.arouter.facade.template;\n\n/**\n * Store policy.\n *\n * @author Alex <a href=\"mailto:zhilong.li"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IProvider.java",
    "chars": 458,
    "preview": "package com.alibaba.android.arouter.facade.template;\n\nimport android.content.Context;\n\n/**\n * Provider interface, base o"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IProviderGroup.java",
    "chars": 468,
    "preview": "package com.alibaba.android.arouter.facade.template;\n\nimport com.alibaba.android.arouter.facade.model.RouteMeta;\n\nimport"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IRouteGroup.java",
    "chars": 420,
    "preview": "package com.alibaba.android.arouter.facade.template;\n\nimport com.alibaba.android.arouter.facade.model.RouteMeta;\n\nimport"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/IRouteRoot.java",
    "chars": 390,
    "preview": "package com.alibaba.android.arouter.facade.template;\n\nimport java.util.Map;\n\n/**\n * Root element.\n *\n * @author Alex <a "
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/facade/template/ISyringe.java",
    "chars": 273,
    "preview": "package com.alibaba.android.arouter.facade.template;\n\n/**\n * Template of syringe\n *\n * @author zhilong <a href=\"mailto:z"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/launcher/ARouter.java",
    "chars": 5184,
    "preview": "package com.alibaba.android.arouter.launcher;\n\nimport android.app.Application;\nimport android.content.Context;\nimport an"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/launcher/_ARouter.java",
    "chars": 17808,
    "preview": "package com.alibaba.android.arouter.launcher;\n\nimport android.app.Activity;\nimport android.app.Application;\nimport andro"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/thread/CancelableCountDownLatch.java",
    "chars": 784,
    "preview": "package com.alibaba.android.arouter.thread;\n\nimport java.util.concurrent.CountDownLatch;\n\n/**\n * As its name.\n *\n * @aut"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/thread/DefaultPoolExecutor.java",
    "chars": 3243,
    "preview": "package com.alibaba.android.arouter.thread;\n\nimport com.alibaba.android.arouter.launcher.ARouter;\nimport com.alibaba.and"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/thread/DefaultThreadFactory.java",
    "chars": 1939,
    "preview": "package com.alibaba.android.arouter.thread;\n\nimport android.support.annotation.NonNull;\n\nimport com.alibaba.android.arou"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/utils/ClassUtils.java",
    "chars": 10185,
    "preview": "package com.alibaba.android.arouter.utils;\n\n// Copy from galaxy sdk ${com.alibaba.android.galaxy.utils.ClassUtils}\n\nimpo"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/utils/Consts.java",
    "chars": 1075,
    "preview": "package com.alibaba.android.arouter.utils;\n\n/**\n * ARouter constants.\n *\n * @author Alex <a href=\"mailto:zhilong.liu@ali"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/utils/DefaultLogger.java",
    "chars": 3980,
    "preview": "package com.alibaba.android.arouter.utils;\n\nimport android.text.TextUtils;\nimport android.util.Log;\n\nimport com.alibaba."
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/utils/MapUtils.java",
    "chars": 908,
    "preview": "package com.alibaba.android.arouter.utils;\n\nimport java.util.Map;\n\n/**\n * Copy from apache common.\n *\n * @author zhilong"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/utils/PackageUtils.java",
    "chars": 2334,
    "preview": "package com.alibaba.android.arouter.utils;\n\nimport android.content.Context;\nimport android.content.SharedPreferences;\nim"
  },
  {
    "path": "arouter-api/src/main/java/com/alibaba/android/arouter/utils/TextUtils.java",
    "chars": 2565,
    "preview": "package com.alibaba.android.arouter.utils;\n\nimport android.net.Uri;\n\nimport java.util.Collections;\nimport java.util.Link"
  },
  {
    "path": "arouter-compiler/build.gradle",
    "chars": 603,
    "preview": "apply plugin: 'java'\n\ncompileJava {\n    sourceCompatibility = '1.8'\n    targetCompatibility = '1.8'\n}\n\ndependencies {\n  "
  },
  {
    "path": "arouter-compiler/gradle.properties",
    "chars": 146,
    "preview": "POM_NAME=ARouter Compiler\nPOM_ARTIFACT_ID=arouter-compiler\nPOM_PACKAGING=jar\nPOM_DESCRIPTION=Compiler for ARouter to fin"
  },
  {
    "path": "arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/entity/RouteDoc.java",
    "chars": 3341,
    "preview": "package com.alibaba.android.arouter.compiler.entity;\n\nimport com.alibaba.fastjson.annotation.JSONField;\n\nimport org.apac"
  },
  {
    "path": "arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/AutowiredProcessor.java",
    "chars": 14692,
    "preview": "package com.alibaba.android.arouter.compiler.processor;\n\nimport com.alibaba.android.arouter.compiler.utils.Consts;\nimpor"
  },
  {
    "path": "arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/BaseProcessor.java",
    "chars": 2665,
    "preview": "package com.alibaba.android.arouter.compiler.processor;\n\nimport com.alibaba.android.arouter.compiler.utils.Logger;\nimpor"
  },
  {
    "path": "arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/InterceptorProcessor.java",
    "chars": 6869,
    "preview": "package com.alibaba.android.arouter.compiler.processor;\n\nimport com.alibaba.android.arouter.compiler.utils.Consts;\nimpor"
  },
  {
    "path": "arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/RouteProcessor.java",
    "chars": 22488,
    "preview": "package com.alibaba.android.arouter.compiler.processor;\n\nimport com.alibaba.android.arouter.compiler.entity.RouteDoc;\nim"
  },
  {
    "path": "arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/Consts.java",
    "chars": 4607,
    "preview": "package com.alibaba.android.arouter.compiler.utils;\n\n/**\n * Some consts used in processors\n *\n * @author Alex <a href=\"m"
  },
  {
    "path": "arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/Logger.java",
    "chars": 1699,
    "preview": "package com.alibaba.android.arouter.compiler.utils;\n\nimport org.apache.commons.lang3.StringUtils;\n\nimport javax.annotati"
  },
  {
    "path": "arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/utils/TypeUtils.java",
    "chars": 3210,
    "preview": "package com.alibaba.android.arouter.compiler.utils;\n\nimport com.alibaba.android.arouter.facade.enums.TypeKind;\n\nimport j"
  },
  {
    "path": "arouter-compiler/src/main/resources/META-INF/gradle/incremental.annotation.processors",
    "chars": 232,
    "preview": "com.alibaba.android.arouter.compiler.processor.RouteProcessor,aggregating\ncom.alibaba.android.arouter.compiler.processor"
  },
  {
    "path": "arouter-gradle-plugin/build.gradle",
    "chars": 214,
    "preview": "apply plugin: 'groovy'\n\ndependencies {\n    compile gradleApi()\n    compile localGroovy()\n}\n\ndependencies {\n    compile '"
  },
  {
    "path": "arouter-gradle-plugin/gradle.properties",
    "chars": 161,
    "preview": "POM_NAME=ARouter Register\nPOM_ARTIFACT_ID=arouter-register\nPOM_PACKAGING=jar\nPOM_DESCRIPTION=Gradle plugin used for arou"
  },
  {
    "path": "arouter-gradle-plugin/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterCodeGenerator.groovy",
    "chars": 4929,
    "preview": "package com.alibaba.android.arouter.register.core\n\nimport com.alibaba.android.arouter.register.utils.Logger\nimport com.a"
  },
  {
    "path": "arouter-gradle-plugin/src/main/groovy/com/alibaba/android/arouter/register/core/RegisterTransform.groovy",
    "chars": 4727,
    "preview": "package com.alibaba.android.arouter.register.core\n\nimport com.alibaba.android.arouter.register.utils.Logger\nimport com.a"
  },
  {
    "path": "arouter-gradle-plugin/src/main/groovy/com/alibaba/android/arouter/register/launch/PluginLaunch.groovy",
    "chars": 1448,
    "preview": "package com.alibaba.android.arouter.register.launch\n\nimport com.alibaba.android.arouter.register.utils.Logger\nimport com"
  },
  {
    "path": "arouter-gradle-plugin/src/main/groovy/com/alibaba/android/arouter/register/utils/Logger.groovy",
    "chars": 853,
    "preview": "package com.alibaba.android.arouter.register.utils\n\nimport org.gradle.api.Project\n\n/**\n * Format log\n *\n * @author zhilo"
  },
  {
    "path": "arouter-gradle-plugin/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanSetting.groovy",
    "chars": 1783,
    "preview": "package com.alibaba.android.arouter.register.utils\n/**\n * register setting\n * @author billy.qi email: qiyilike@163.com\n "
  },
  {
    "path": "arouter-gradle-plugin/src/main/groovy/com/alibaba/android/arouter/register/utils/ScanUtil.groovy",
    "chars": 3395,
    "preview": "package com.alibaba.android.arouter.register.utils\n\nimport com.alibaba.android.arouter.register.core.RegisterTransform\ni"
  },
  {
    "path": "arouter-gradle-plugin/src/main/resources/META-INF/gradle-plugins/com.alibaba.arouter.properties",
    "chars": 77,
    "preview": "implementation-class=com.alibaba.android.arouter.register.launch.PluginLaunch"
  },
  {
    "path": "arouter-idea-plugin/build.gradle",
    "chars": 608,
    "preview": "plugins {\n    id 'org.jetbrains.kotlin.jvm'\n    id \"org.jetbrains.intellij\" version '0.3.12'\n}\n\nintellij {\n    version s"
  },
  {
    "path": "arouter-idea-plugin/src/main/kotlin/com/alibaba/android/arouter/idea/extensions/NavigationLineMarker.kt",
    "chars": 4800,
    "preview": "package com.alibaba.android.arouter.idea.extensions\n\nimport com.intellij.codeHighlighting.Pass\nimport com.intellij.codeI"
  },
  {
    "path": "arouter-idea-plugin/src/main/resources/META-INF/plugin.xml",
    "chars": 594,
    "preview": "<idea-plugin>\n    <id>arouter-roadsign</id>\n    <name>ARouter Helper</name>\n    <version>1.0.0</version>\n    <vendor ema"
  },
  {
    "path": "build.gradle",
    "chars": 637,
    "preview": "buildscript {\n    ext.kotlin_version = '1.4.10'\n    ext.arouter_register_version = '1.0.2'\n\n    repositories {\n        m"
  },
  {
    "path": "gradle/publish.gradle",
    "chars": 5018,
    "preview": "/*\n * Copyright 2013 Chris Banes\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 230,
    "preview": "#Fri Jun 12 21:40:29 CST 2020\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 1545,
    "preview": "## Project-wide Gradle settings.\n#\n# For more details on how to configure your build environment visit\n# http://www.grad"
  },
  {
    "path": "gradlew",
    "chars": 4971,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2404,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "module-java/build.gradle",
    "chars": 1215,
    "preview": "apply plugin: 'com.android.library'\n\ndependencies {\n    implementation project(':arouter-annotation')\n    implementation"
  },
  {
    "path": "module-java/src/main/AndroidManifest.xml",
    "chars": 1205,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/BlankFragment.java",
    "chars": 1577,
    "preview": "package com.alibaba.android.arouter.demo.module1;\n\n\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nim"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/MainLooper.java",
    "chars": 600,
    "preview": "package com.alibaba.android.arouter.demo.module1;\n\nimport android.os.Handler;\nimport android.os.Looper;\n\npublic class Ma"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/TestInterceptor90.java",
    "chars": 1085,
    "preview": "package com.alibaba.android.arouter.demo.module1;\n\nimport android.content.Context;\nimport android.util.Log;\n\nimport com."
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/TestModule2Activity.java",
    "chars": 470,
    "preview": "package com.alibaba.android.arouter.demo.module1;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bu"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/TestModuleActivity.java",
    "chars": 425,
    "preview": "package com.alibaba.android.arouter.demo.module1;\n\nimport android.app.Activity;\nimport android.os.Bundle;\n\nimport com.al"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/TestWebview.java",
    "chars": 594,
    "preview": "package com.alibaba.android.arouter.demo.module1;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/BaseActivity.java",
    "chars": 337,
    "preview": "package com.alibaba.android.arouter.demo.module1.testactivity;\n\nimport android.support.v7.app.AppCompatActivity;\n\nimport"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/Test1Activity.java",
    "chars": 2668,
    "preview": "package com.alibaba.android.arouter.demo.module1.testactivity;\n\nimport android.os.Bundle;\nimport android.widget.TextView"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/Test2Activity.java",
    "chars": 891,
    "preview": "package com.alibaba.android.arouter.demo.module1.testactivity;\n\nimport android.os.Bundle;\nimport android.support.v7.app."
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/Test3Activity.java",
    "chars": 1144,
    "preview": "package com.alibaba.android.arouter.demo.module1.testactivity;\n\nimport android.os.Bundle;\nimport android.support.v7.app."
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/Test4Activity.java",
    "chars": 847,
    "preview": "package com.alibaba.android.arouter.demo.module1.testactivity;\n\nimport android.os.Bundle;\nimport android.support.v7.app."
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testactivity/TestDynamicActivity.java",
    "chars": 336,
    "preview": "package com.alibaba.android.arouter.demo.module1.testactivity;\n\nimport android.os.Bundle;\n\n// 用于测试不标注 Route 的情况下,动态增加路由\n"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testinterceptor/Test1Interceptor.java",
    "chars": 2697,
    "preview": "package com.alibaba.android.arouter.demo.module1.testinterceptor;\n\nimport android.app.AlertDialog;\nimport android.conten"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testservice/HelloServiceImpl.java",
    "chars": 982,
    "preview": "package com.alibaba.android.arouter.demo.module1.testservice;\n\nimport android.content.Context;\nimport android.util.Log;\n"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testservice/JsonServiceImpl.java",
    "chars": 992,
    "preview": "package com.alibaba.android.arouter.demo.module1.testservice;\n\nimport android.content.Context;\n\nimport com.alibaba.andro"
  },
  {
    "path": "module-java/src/main/java/com/alibaba/android/arouter/demo/module1/testservice/SingleService.java",
    "chars": 727,
    "preview": "package com.alibaba.android.arouter.demo.module1.testservice;\n\nimport android.content.Context;\nimport android.widget.Toa"
  },
  {
    "path": "module-java/src/main/res/layout/activity_test1.xml",
    "chars": 1055,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  "
  },
  {
    "path": "module-java/src/main/res/layout/activity_test2.xml",
    "chars": 773,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  "
  },
  {
    "path": "module-java/src/main/res/layout/activity_test4.xml",
    "chars": 601,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  "
  },
  {
    "path": "module-java/src/main/res/layout/activity_test_module.xml",
    "chars": 770,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  "
  },
  {
    "path": "module-java/src/main/res/layout/activity_test_module2.xml",
    "chars": 770,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  "
  },
  {
    "path": "module-java/src/main/res/layout/activity_test_webview.xml",
    "chars": 524,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  "
  },
  {
    "path": "module-java/src/main/res/values/dimens.xml",
    "chars": 211,
    "preview": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal"
  },
  {
    "path": "module-java/src/main/res/values/strings.xml",
    "chars": 24,
    "preview": "<resources></resources>\n"
  },
  {
    "path": "module-java-export/build.gradle",
    "chars": 1135,
    "preview": "apply plugin: 'com.android.library'\n\ndependencies {\n    implementation project(':arouter-annotation')\n    implementation"
  },
  {
    "path": "module-java-export/src/main/AndroidManifest.xml",
    "chars": 175,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/Entrance.java",
    "chars": 555,
    "preview": "package com.alibaba.android.arouter.demo.service;\n\nimport android.content.Context;\n\nimport com.alibaba.android.arouter.l"
  },
  {
    "path": "module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/HelloService.java",
    "chars": 389,
    "preview": "package com.alibaba.android.arouter.demo.service;\n\nimport com.alibaba.android.arouter.facade.template.IProvider;\n\n/**\n *"
  },
  {
    "path": "module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/model/TestObj.java",
    "chars": 402,
    "preview": "package com.alibaba.android.arouter.demo.service.model;\n\n/**\n * TODO:Feature\n *\n * @author zhilong <a href=\"mailto:zhilo"
  },
  {
    "path": "module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/model/TestParcelable.java",
    "chars": 1177,
    "preview": "package com.alibaba.android.arouter.demo.service.model;\n\nimport android.os.Parcel;\nimport android.os.Parcelable;\n\n/**\n *"
  },
  {
    "path": "module-java-export/src/main/java/com/alibaba/android/arouter/demo/service/model/TestSerializable.java",
    "chars": 383,
    "preview": "package com.alibaba.android.arouter.demo.service.model;\n\nimport java.io.Serializable;\n\n/**\n * Created by @author joker o"
  },
  {
    "path": "module-kotlin/build.gradle",
    "chars": 1243,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt'\napply plugin: 'kotlin-and"
  },
  {
    "path": "module-kotlin/src/main/AndroidManifest.xml",
    "chars": 529,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          pa"
  },
  {
    "path": "module-kotlin/src/main/java/com/alibaba/android/arouter/demo/kotlin/KotlinTestActivity.kt",
    "chars": 791,
    "preview": "package com.alibaba.android.arouter.demo.kotlin\n\nimport android.app.Activity\nimport android.os.Bundle\nimport com.alibaba"
  },
  {
    "path": "module-kotlin/src/main/java/com/alibaba/android/arouter/demo/kotlin/TestNormalActivity.java",
    "chars": 456,
    "preview": "package com.alibaba.android.arouter.demo.kotlin;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bun"
  },
  {
    "path": "module-kotlin/src/main/res/layout/activity_kotlin_test.xml",
    "chars": 488,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    "
  },
  {
    "path": "module-kotlin/src/main/res/layout/activity_test_normal.xml",
    "chars": 463,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout\n    xmlns:android=\"http://schemas.an"
  },
  {
    "path": "module-kotlin/src/main/res/values/dimens.xml",
    "chars": 211,
    "preview": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal"
  },
  {
    "path": "module-kotlin/src/main/res/values/strings.xml",
    "chars": 24,
    "preview": "<resources></resources>\n"
  },
  {
    "path": "settings.gradle",
    "chars": 240,
    "preview": "include ':app'\ninclude ':arouter-api'\ninclude ':arouter-compiler'\ninclude ':arouter-annotation'\ninclude ':module-java'\ni"
  }
]

// ... and 4 more files (download for full content)

About this extraction

This page contains the full source code of the alibaba/ARouter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 148 files (329.0 KB), approximately 80.3k tokens, and a symbol index with 426 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!