├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── layout
│ │ │ │ ├── activity_test.xml
│ │ │ │ └── activity_main.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_background.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── smart
│ │ │ │ └── router
│ │ │ │ └── app
│ │ │ │ ├── App.java
│ │ │ │ ├── TestActivity.java
│ │ │ │ ├── SampleInterceptor.java
│ │ │ │ └── MainActivity.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── smart
│ │ │ └── router
│ │ │ └── app
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── smart
│ │ └── router
│ │ └── app
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── router
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── smart
│ │ │ └── router
│ │ │ └── router
│ │ │ ├── RouteResult.java
│ │ │ ├── ParamInjector.java
│ │ │ ├── RouteCallback.java
│ │ │ ├── InterceptorTable.java
│ │ │ ├── RouteInterceptor.java
│ │ │ ├── RouteTable.java
│ │ │ ├── TargetInterceptors.java
│ │ │ ├── matcher
│ │ │ ├── AbsImplicitMatcher.java
│ │ │ ├── DirectMatcher.java
│ │ │ ├── BrowserMatcher.java
│ │ │ ├── Matcher.java
│ │ │ ├── AbsExplicitMatcher.java
│ │ │ ├── ImplicitMatcher.java
│ │ │ ├── AbsMatcher.java
│ │ │ └── SchemeMatcher.java
│ │ │ ├── util
│ │ │ └── RLog.java
│ │ │ ├── Configuration.java
│ │ │ ├── MatcherRegistry.java
│ │ │ ├── IRouter.java
│ │ │ ├── SmartRouter.java
│ │ │ ├── AptHub.java
│ │ │ ├── RouteRequest.java
│ │ │ ├── AbsRouter.java
│ │ │ └── RealRouter.java
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── smart
│ │ │ └── router
│ │ │ └── router
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── smart
│ │ └── router
│ │ └── router
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
├── build.gradle
└── publish.gradle
├── annotation
├── .gitignore
├── build.gradle
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── smart
│ │ └── router
│ │ └── annotation
│ │ ├── Interceptor.java
│ │ ├── InjectParam.java
│ │ └── Route.java
└── publish.gradle
├── compiler
├── .gitignore
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── services
│ │ │ └── javax.annotation.processing.Processor
│ │ └── java
│ │ └── com
│ │ └── smart
│ │ └── router
│ │ └── compiler
│ │ ├── util
│ │ ├── Logger.java
│ │ └── Consts.java
│ │ └── processor
│ │ ├── InterceptorProcessor.java
│ │ ├── RouteProcessor.java
│ │ └── InjectParamProcessor.java
├── build.gradle
└── publish.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── .idea
├── encodings.xml
├── runConfigurations.xml
├── modules.xml
├── gradle.xml
└── misc.xml
├── VERSION.properties
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/router/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/annotation/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/compiler/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':annotation', ':compiler', ':router'
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SmartRouter
3 |
4 |
--------------------------------------------------------------------------------
/router/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | router
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/router/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kongpengcheng/SmartRoute/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/VERSION.properties:
--------------------------------------------------------------------------------
1 | # router gradle plugin version
2 | GRADLE_PLUGIN_VERSION=1.1.1
3 | # router library version
4 | ROUTER_VERSION=1.1.3
5 | # compiler library version
6 | COMPILER_VERSION=1.1.2
7 | # annotation library version
8 | ANNOTATION_VERSION=0.3.0
--------------------------------------------------------------------------------
/annotation/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | dependencies {
4 | implementation fileTree(dir: 'libs', include: ['*.jar'])
5 | }
6 |
7 | sourceCompatibility = "1.7"
8 | targetCompatibility = "1.7"
9 | //apply from: 'publish.gradle'
10 |
--------------------------------------------------------------------------------
/compiler/src/main/resources/META-INF/services/javax.annotation.processing.Processor:
--------------------------------------------------------------------------------
1 | com.smart.router.compiler.processor.RouteProcessor
2 | com.smart.router.compiler.processor.InterceptorProcessor
3 | com.smart.router.compiler.processor.InjectParamProcessor
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/RouteResult.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | /**
4 | * Result for each route.
5 | *
6 | * Created by Harry.Kong.
7 | */
8 | public enum RouteResult {
9 | SUCCEED,
10 | INTERCEPTED,
11 | FAILED
12 | }
13 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Nov 07 14:14:50 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/ParamInjector.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | /**
4 | * Interface that help to generate param class.
5 | *
6 | * Created by Harry.Kong.
7 | */
8 | public interface ParamInjector {
9 | /**
10 | * Inject params.
11 | *
12 | * @param obj Activity or fragment instance.
13 | */
14 | void inject(Object obj);
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/RouteCallback.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import android.net.Uri;
4 |
5 | /**
6 | * Created by Harry.Kong..
7 | */
8 | public interface RouteCallback {
9 | /**
10 | * Callback
11 | *
12 | * @param state {@link RouteResult}
13 | * @param uri Uri
14 | * @param message notice msg
15 | */
16 | void callback(RouteResult state, Uri uri, String message);
17 | }
18 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/InterceptorTable.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import java.util.Map;
4 |
5 | /**
6 | * Interceptor table mapping.
7 | *
8 | * Created by Harry.Kong.
9 | */
10 | public interface InterceptorTable {
11 | /**
12 | * Mapping between name and interceptor.
13 | *
14 | * @param map name -> interceptor.
15 | */
16 | void handle(Map> map);
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/smart/router/app/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.app;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/router/src/test/java/com/smart/router/router/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/RouteInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Interceptor before route.
7 | *
8 | * Created by Harry.Kong.
9 | */
10 | public interface RouteInterceptor {
11 | /**
12 | * @param context Context
13 | * @param routeRequest RouteRequest
14 | * @return True if you want to intercept this route, false otherwise.
15 | */
16 | boolean intercept(Context context, RouteRequest routeRequest);
17 | }
18 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/RouteTable.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import java.util.Map;
4 |
5 | /**
6 | * Route table mapping.
7 | *
8 | * Created by Harry.Kong.
9 | */
10 | public interface RouteTable {
11 | /**
12 | * Mapping between uri and target, the target class may be an {@link android.app.Activity},
13 | * {@link android.app.Fragment} or {@link android.support.v4.app.Fragment}.
14 | *
15 | * @param map uri -> target.
16 | */
17 | void handle(Map> map);
18 | }
19 |
--------------------------------------------------------------------------------
/annotation/src/main/java/com/smart/router/annotation/Interceptor.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by Harry.Kong.
10 | * Time 2017/11/8.
11 | * Description:拦截
12 | */
13 | @Target(ElementType.TYPE)
14 | @Retention(RetentionPolicy.CLASS)
15 | public @interface Interceptor {
16 | /**
17 | * Interceptor name.
18 | */
19 | String value();
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/smart/router/app/App.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.app;
2 |
3 | import android.app.Application;
4 |
5 | import com.smart.router.router.Configuration;
6 | import com.smart.router.router.SmartRouter;
7 |
8 | public class App extends Application {
9 | @Override
10 | public void onCreate() {
11 | super.onCreate();
12 | // init
13 | SmartRouter.initialize(new Configuration.Builder()
14 | .setDebuggable(BuildConfig.DEBUG)
15 | .registerModules("app")
16 | .build());
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/annotation/src/main/java/com/smart/router/annotation/InjectParam.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by Harry.Kong.
10 | * Time 2017/11/8.
11 | * Description:参数
12 | */
13 | @Target(ElementType.FIELD)
14 | @Retention(RetentionPolicy.CLASS)
15 | public @interface InjectParam {
16 | /**
17 | * Map param field with the specify key in bundle.
18 | */
19 | String key() default "";
20 | }
21 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/TargetInterceptors.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import java.util.Map;
4 |
5 | /**
6 | * Target interceptorTable mapping.
7 | *
8 | * Created by Harry.Kong.
9 | */
10 | public interface TargetInterceptors {
11 | /**
12 | * Mapping between target and interceptorTable, the target class may be an {@link android.app.Activity},
13 | * {@link android.app.Fragment} or {@link android.support.v4.app.Fragment}.
14 | *
15 | * @param map target -> interceptorTable.
16 | */
17 | void handle(Map, String[]> map);
18 | }
19 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/annotation/src/main/java/com/smart/router/annotation/Route.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.annotation;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Created by Harry.Kong.
10 | * Time 2017/11/8.
11 | * Description:路由
12 | */
13 | @Target(ElementType.TYPE)
14 | @Retention(RetentionPolicy.CLASS)
15 | public @interface Route {
16 | /**
17 | * Route path.
18 | */
19 | String[] value();
20 |
21 | /**
22 | * The interceptors' name.
23 | */
24 | String[] interceptors() default {};
25 | }
26 |
--------------------------------------------------------------------------------
/compiler/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 | tasks.withType(JavaCompile) {
3 | options.encoding = "UTF-8"
4 | }
5 |
6 | Properties version = new Properties()
7 | version.load(project.file('../VERSION.properties').newDataInputStream())
8 | def annoVersion = version.getProperty("ANNOTATION_VERSION")
9 |
10 | dependencies {
11 | compile fileTree(include: ['*.jar'], dir: 'libs')
12 | compile 'com.squareup:javapoet:1.9.0'
13 | // compile project(':annotation')
14 | compile 'com.kong.router:annotation:0.3.0'
15 | }
16 |
17 | sourceCompatibility = JavaVersion.VERSION_1_7
18 | targetCompatibility = JavaVersion.VERSION_1_7
19 |
20 | //apply from: 'publish.gradle'
21 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/matcher/AbsImplicitMatcher.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router.matcher;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.support.annotation.Nullable;
7 | /**
8 | * Created by Harry.Kong.
9 | * Time 2017/11/8.
10 | * Description:Base mather for implicit intent.
11 | */
12 | public abstract class AbsImplicitMatcher extends AbsMatcher {
13 |
14 | public AbsImplicitMatcher(int priority) {
15 | super(priority);
16 | }
17 |
18 | @Override
19 | public Object generate(Context context, Uri uri, @Nullable Class> target) {
20 | return new Intent(Intent.ACTION_VIEW, uri);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/smart/router/app/TestActivity.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.app;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 |
6 | import com.smart.router.annotation.InjectParam;
7 | import com.smart.router.annotation.Route;
8 | import com.smart.router.router.SmartRouter;
9 |
10 | @Route("test")
11 | public class TestActivity extends AppCompatActivity {
12 | @InjectParam
13 | String id = "0000";
14 | @InjectParam(key = "status")
15 | String sts = "default";
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_test);
20 | SmartRouter.injectParams(this);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/matcher/DirectMatcher.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router.matcher;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.support.annotation.Nullable;
6 |
7 | import com.smart.router.router.RouteRequest;
8 |
9 | /**
10 | * Created by Harry.Kong.
11 | * Time 2017/11/8.
12 | * Description:Absolutely matcher.
13 | */
14 | public class DirectMatcher extends AbsExplicitMatcher {
15 |
16 | public DirectMatcher(int priority) {
17 | super(priority);
18 | }
19 |
20 | @Override
21 | public boolean match(Context context, Uri uri, @Nullable String route, RouteRequest routeRequest) {
22 | return !isEmpty(route) && uri.toString().equals(route);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/router/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/smart/router/app/SampleInterceptor.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.app;
2 |
3 | import android.content.Context;
4 | import android.widget.Toast;
5 |
6 | import com.smart.router.annotation.Interceptor;
7 | import com.smart.router.router.RouteInterceptor;
8 | import com.smart.router.router.RouteRequest;
9 |
10 |
11 | /**
12 | * 自定义拦截器,通过注解指定name,就可以在Route中引用
13 | *
14 | */
15 | @Interceptor("SampleInterceptor")
16 | public class SampleInterceptor implements RouteInterceptor {
17 | @Override
18 | public boolean intercept(Context context, RouteRequest routeRequest) {
19 | Toast.makeText(context, String.format("Intercepted: {uri: %s, interceptor: %s}",
20 | routeRequest.getUri().toString(), SampleInterceptor.class.getName()),
21 | Toast.LENGTH_LONG).show();
22 | return true;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/smart/router/app/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.app;
2 |
3 | import android.support.v7.app.AppCompatActivity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Button;
7 |
8 | import com.smart.router.router.SmartRouter;
9 |
10 |
11 | public class MainActivity extends AppCompatActivity implements View.OnClickListener {
12 | Button btn_test;
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | setContentView(R.layout.activity_main);
18 | btn_test = findViewById(R.id.btn_test);
19 | btn_test.setOnClickListener(this);
20 | }
21 |
22 | @Override
23 | public void onClick(View view) {
24 | if (view == btn_test) {
25 | SmartRouter.build("test").go(this);
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/matcher/BrowserMatcher.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router.matcher;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.support.annotation.Nullable;
6 |
7 | import com.smart.router.router.RouteRequest;
8 |
9 | /**
10 | * Created by Harry.Kong.
11 | * Time 2017/11/8.
12 | * Description:This matcher will generate an intent with an {@link android.content.Intent#ACTION_VIEW} action
13 | */
14 | public class BrowserMatcher extends AbsImplicitMatcher {
15 | public BrowserMatcher(int priority) {
16 | super(priority);
17 | }
18 |
19 | @Override
20 | public boolean match(Context context, Uri uri, @Nullable String route, RouteRequest routeRequest) {
21 | return (uri.toString().toLowerCase().startsWith("http://")
22 | || uri.toString().toLowerCase().startsWith("https://"));
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/smart/router/app/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.app;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.smart.router.smartrouter", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/router/src/androidTest/java/com/smart/router/router/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.smart.router.router.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/util/RLog.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router.util;
2 |
3 | import android.util.Log;
4 |
5 | /**
6 | * Internal simple log.
7 | *
8 | */
9 | public class RLog {
10 | private static final String TAG = "SmartRouter";
11 | private static boolean sLoggable = false;
12 |
13 | public static void showLog(boolean loggable) {
14 | sLoggable = loggable;
15 | }
16 |
17 | public static void i(String msg) {
18 | if (sLoggable) {
19 | Log.i(TAG, msg);
20 | }
21 | }
22 |
23 | public static void i(String tag, String msg) {
24 | if (sLoggable) {
25 | Log.i(tag, msg);
26 | }
27 | }
28 |
29 | public static void w(String msg) {
30 | if (sLoggable) {
31 | Log.w(TAG, msg);
32 | }
33 | }
34 |
35 | public static void e(String msg) {
36 | Log.e(TAG, msg);
37 | }
38 |
39 | public static void e(String msg, Throwable tr) {
40 | Log.e(TAG, msg, tr);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/router/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | android {
3 | compileSdkVersion 26
4 | defaultConfig {
5 | minSdkVersion 15
6 | targetSdkVersion 26
7 | versionCode 1
8 | versionName "1.0"
9 |
10 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
11 |
12 | }
13 |
14 | lintOptions {
15 | checkReleaseBuilds false
16 | abortOnError false
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 |
25 | }
26 |
27 | dependencies {
28 | implementation fileTree(dir: 'libs', include: ['*.jar'])
29 | api project(':annotation')
30 | implementation 'com.android.support:appcompat-v7:26.1.0'
31 | testImplementation 'junit:junit:4.12'
32 | androidTestImplementation 'com.android.support.test:runner:1.0.1'
33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
34 | // 这里不能使用implementation,因为pom依赖不识别
35 | compile 'com.kong.router:annotation:0.3.0'
36 | }
37 | apply from: 'publish.gradle'
38 |
39 |
40 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/Configuration.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | /**
4 | * Initialization.
5 | *
6 | * Created by Harry.Kong.
7 | */
8 | public class Configuration {
9 | boolean debuggable;
10 | String[] modules;
11 |
12 | private Configuration() {
13 | }
14 |
15 | public static class Builder {
16 | private boolean debuggable;
17 | private String[] modules;
18 |
19 | public Builder setDebuggable(boolean debuggable) {
20 | this.debuggable = debuggable;
21 | return this;
22 | }
23 |
24 | public Builder registerModules(String... modules) {
25 | this.modules = modules;
26 | return this;
27 | }
28 |
29 | public Configuration build() {
30 | if (modules == null || modules.length == 0) {
31 | throw new RuntimeException("You must call registerModules() to initialize SmartRouter.");
32 | }
33 | Configuration configuration = new Configuration();
34 | configuration.debuggable = this.debuggable;
35 | configuration.modules = this.modules;
36 | return configuration;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/matcher/Matcher.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router.matcher;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.support.annotation.Nullable;
6 |
7 | import com.smart.router.router.RouteRequest;
8 |
9 |
10 | /**
11 | * Match rule.
12 | *
13 | */
14 | interface Matcher extends Comparable {
15 | /**
16 | * Determines if the given uri matches current route.
17 | *
18 | * @param context Context.
19 | * @param uri the given uri.
20 | * @param route path in route table.
21 | * @param routeRequest {@link RouteRequest}.
22 | * @return True if matched, false otherwise.
23 | */
24 | boolean match(Context context, Uri uri, @Nullable String route, RouteRequest routeRequest);
25 |
26 | /**
27 | * Called when {@link #match(Context, Uri, String, RouteRequest)} returns true.
28 | *
29 | * @param context Context.
30 | * @param uri The given uri.
31 | * @param target Route target. Activity or Fragment.
32 | * @return An object(intent/fragment) that the matcher generated.
33 | */
34 | Object generate(Context context, Uri uri, @Nullable Class> target);
35 | }
36 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/MatcherRegistry.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import com.smart.router.router.matcher.AbsMatcher;
4 | import com.smart.router.router.matcher.BrowserMatcher;
5 | import com.smart.router.router.matcher.DirectMatcher;
6 | import com.smart.router.router.matcher.ImplicitMatcher;
7 | import com.smart.router.router.matcher.SchemeMatcher;
8 |
9 | import java.util.ArrayList;
10 | import java.util.Collections;
11 | import java.util.List;
12 |
13 | /**
14 | * AbsMatcher registry.
15 | *
16 | * Created by Harry.Kong.
17 | */
18 | public class MatcherRegistry {
19 |
20 | private static final List registry = new ArrayList<>();
21 |
22 | static {
23 | registry.add(new DirectMatcher(0x1000));
24 | registry.add(new SchemeMatcher(0x0100));
25 | registry.add(new ImplicitMatcher(0x0010));
26 | registry.add(new BrowserMatcher(0x0000));
27 | Collections.sort(registry);
28 | }
29 |
30 | public static void register(AbsMatcher matcher) {
31 | registry.add(matcher);
32 | Collections.sort(registry);
33 | }
34 |
35 | public static List getMatcher() {
36 | return registry;
37 | }
38 |
39 | public static void clear() {
40 | registry.clear();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/compiler/src/main/java/com/smart/router/compiler/util/Logger.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.compiler.util;
2 |
3 | import javax.annotation.processing.Messager;
4 | import javax.lang.model.element.Element;
5 | import javax.tools.Diagnostic;
6 |
7 | /**
8 | * Created by Harry.Kong.
9 | * Time 2017/11/8.
10 | * Email kongpengcheng@aliyun.com.
11 | * Description:日志
12 | */
13 | public class Logger {
14 | private Messager messager;
15 |
16 | public Logger(Messager messager) {
17 | this.messager = messager;
18 | }
19 |
20 | public void info(CharSequence info) {
21 | messager.printMessage(Diagnostic.Kind.NOTE, info);
22 | }
23 |
24 | public void info(Element element, CharSequence info) {
25 | messager.printMessage(Diagnostic.Kind.NOTE, info, element);
26 | }
27 |
28 | public void warn(CharSequence info) {
29 | messager.printMessage(Diagnostic.Kind.WARNING, info);
30 | }
31 |
32 | public void warn(Element element, CharSequence info) {
33 | messager.printMessage(Diagnostic.Kind.WARNING, info, element);
34 | }
35 |
36 | public void error(CharSequence info) {
37 | messager.printMessage(Diagnostic.Kind.ERROR, info);
38 | }
39 |
40 | public void error(Element element, CharSequence info) {
41 | messager.printMessage(Diagnostic.Kind.ERROR, info, element);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/matcher/AbsExplicitMatcher.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router.matcher;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.support.annotation.Nullable;
8 | import android.support.v4.app.Fragment;
9 | /**
10 | * Created by Harry.Kong.
11 | * Time 2017/11/8.
12 | * Description:mather for explicit intent and fragment.
13 | */
14 | public abstract class AbsExplicitMatcher extends AbsMatcher {
15 |
16 | public AbsExplicitMatcher(int priority) {
17 | super(priority);
18 | }
19 |
20 | @Override
21 | public Object generate(Context context, Uri uri, @Nullable Class> target) {
22 | if (target == null) {
23 | return null;
24 | }
25 | Object result = null;
26 | if (Activity.class.isAssignableFrom(target)) {
27 | result = new Intent(context, target);
28 | } else if (Fragment.class.isAssignableFrom(target)) { // v4.fragment
29 | try {
30 | result = target.newInstance();
31 | } catch (Exception e) {
32 | e.printStackTrace();
33 | }
34 | } else if (android.app.Fragment.class.isAssignableFrom(target)) {
35 | try {
36 | result = target.newInstance();
37 | } catch (Exception e) {
38 | e.printStackTrace();
39 | }
40 | }
41 | return result;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/matcher/ImplicitMatcher.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router.matcher;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.pm.PackageManager;
6 | import android.content.pm.ResolveInfo;
7 | import android.net.Uri;
8 | import android.support.annotation.Nullable;
9 |
10 | import com.smart.router.router.RouteRequest;
11 |
12 | /**
13 | * Created by Harry.Kong.
14 | * Time 2017/11/8.
15 | * Description:Support for implicit intent exclude scheme "http(s)",
16 | * cause we may want to resolve them in custom matcher, such as {@link SchemeMatcher},
17 | */
18 | public class ImplicitMatcher extends AbsImplicitMatcher {
19 | public ImplicitMatcher(int priority) {
20 | super(priority);
21 | }
22 |
23 | @Override
24 | public boolean match(Context context, Uri uri, @Nullable String route, RouteRequest routeRequest) {
25 | if (uri.toString().toLowerCase().startsWith("http://")
26 | || uri.toString().toLowerCase().startsWith("https://")) {
27 | return false;
28 | }
29 | ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(
30 | new Intent(Intent.ACTION_VIEW, uri), PackageManager.MATCH_DEFAULT_ONLY);
31 | if (resolveInfo != null) {
32 | // bundle parser
33 | if (uri.getQuery() != null) {
34 | parseParams(uri, routeRequest);
35 | }
36 | return true;
37 | }
38 | return false;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 26
5 | defaultConfig {
6 | applicationId "com.smart.router.smartrouter"
7 | minSdkVersion 15
8 | targetSdkVersion 26
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | javaCompileOptions {
13 | annotationProcessorOptions {
14 | arguments = ["moduleName": project.name]
15 | }
16 | }
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | }
25 |
26 | dependencies {
27 | implementation fileTree(dir: 'libs', include: ['*.jar'])
28 |
29 | implementation 'com.android.support:appcompat-v7:26.1.0'
30 | implementation 'com.android.support.constraint:constraint-layout:1.0.2'
31 | testImplementation 'junit:junit:4.12'
32 | androidTestImplementation 'com.android.support.test:runner:1.0.1'
33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
34 | implementation project(':router')
35 | annotationProcessor project(':compiler')
36 | // compile 'com.kong.router:annotation:0.3.0'
37 | // annotationProcessor 'com.kong.router:compiler:1.1.1'
38 | // compile 'com.kong.router:router:1.1.1'
39 |
40 |
41 |
42 | //
43 | // annotationProcessor project(':compiler')
44 | // compile project(':router')
45 | //
46 | //
47 | // compile project(path: ':annotation')
48 | }
49 |
50 | repositories {
51 | jcenter()
52 | google()
53 | }
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/compiler/src/main/java/com/smart/router/compiler/util/Consts.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.compiler.util;
2 |
3 | /**
4 | * Created by Harry.Kong.
5 | * Time 2017/11/8.
6 | * Email kongpengcheng@aliyun.com.
7 | * Description:常量
8 | */
9 | public class Consts {
10 | public static final String OPTION_MODULE_NAME = "moduleName";
11 | public static final String CLASS_JAVA_DOC = "Generated by Router. Do not edit it!\n";
12 |
13 | public static final String DOT = ".";
14 | public static final String PACKAGE_NAME = "com.smart.router.router";
15 | public static final String ROUTE_TABLE = "RouteTable";
16 | public static final String ROUTE_TABLE_FULL_NAME = PACKAGE_NAME + DOT + ROUTE_TABLE;
17 | public static final String ACTIVITY_FULL_NAME = "android.app.Activity";
18 | public static final String FRAGMENT_FULL_NAME = "android.app.Fragment";
19 | public static final String FRAGMENT_V4_FULL_NAME = "android.support.v4.app.Fragment";
20 |
21 | public static final String ROUTE_ANNOTATION_TYPE = "com.smart.router.annotation.Route";
22 | public static final String INTERCEPTOR_ANNOTATION_TYPE = "com.smart.router.annotation.Interceptor";
23 | public static final String PARAM_ANNOTATION_TYPE = "com.smart.router.annotation.InjectParam";
24 |
25 | public static final String HANDLE = "handle";
26 | public static final String INTERCEPTOR_INTERFACE = PACKAGE_NAME + DOT + "RouteInterceptor";
27 |
28 | public static final String INTERCEPTOR_TABLE = "InterceptorTable";
29 |
30 | public static final String TABLE_INTERCEPTORS = "TargetInterceptors";
31 |
32 | public static final String METHOD_INJECT = "inject";
33 | // XXXActivity$$Router$$Params
34 | public static final String INNER_CLASS_NAME = "$$Router$$ParamInjector";
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/annotation/publish.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven-publish'
2 | apply plugin: 'com.jfrog.bintray'
3 |
4 | Properties config = new Properties()
5 | config.load(project.file('../VERSION.properties').newDataInputStream())
6 | def VERSION = config.getProperty("ANNOTATION_VERSION")
7 | def GROUP = 'com.kong.router'
8 | def ARTIFACT_ID = 'annotation'
9 |
10 | group = GROUP
11 | version = VERSION
12 |
13 | task sourcesJar(type: Jar, dependsOn: classes) {
14 | from sourceSets.main.allSource
15 | classifier = 'sources'
16 | }
17 |
18 | artifacts {
19 | archives sourcesJar
20 | }
21 |
22 | publishing {
23 | publications {
24 | bintray(MavenPublication) {
25 | groupId GROUP
26 | artifactId ARTIFACT_ID
27 | version VERSION
28 |
29 | artifact sourcesJar
30 | from components.java
31 | }
32 | }
33 | }
34 |
35 |
36 | bintray {
37 | Properties properties = new Properties()
38 | boolean hasLocalFile = false
39 | if (project.rootProject.file('local.properties').exists()) {
40 | hasLocalFile = true
41 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
42 | }
43 | user = hasLocalFile ? properties.getProperty("bintray.user") : ""
44 | key = hasLocalFile ? properties.getProperty("bintray.apikey") : ""
45 |
46 | publications = ['bintray']
47 | pkg {
48 | repo = "smartannotation"
49 | name = "router-annotation"
50 | websiteUrl = 'https://github.com/kongpengcheng/SmartRoute'
51 | vcsUrl = 'https://github.com/kongpengcheng/SmartRoute.git'
52 | desc = "Annotation for Router library."
53 | labels = ["Android", "Router", "annotation"]
54 | licenses = ["Apache-2.0"]
55 | publicDownloadNumbers = true
56 | publish = true
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/compiler/publish.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven-publish'
2 | apply plugin: 'com.jfrog.bintray'
3 |
4 | Properties config = new Properties()
5 | config.load(project.file('../VERSION.properties').newDataInputStream())
6 | def VERSION = config.getProperty("COMPILER_VERSION")
7 | def GROUP = 'com.kong.router'
8 | def ARTIFACT_ID = 'compiler'
9 |
10 | group = GROUP
11 | version = VERSION
12 |
13 | task sourcesJar(type: Jar, dependsOn: classes) {
14 | from sourceSets.main.allSource
15 | classifier = 'sources'
16 | }
17 |
18 | artifacts {
19 | archives sourcesJar
20 | }
21 |
22 | publishing {
23 | publications {
24 | bintray(MavenPublication) {
25 | groupId GROUP
26 | artifactId ARTIFACT_ID
27 | version VERSION
28 |
29 | artifact sourcesJar
30 | from components.java
31 | }
32 | }
33 | }
34 |
35 | bintray {
36 | Properties properties = new Properties()
37 | boolean hasLocalFile = false
38 | if (project.rootProject.file('local.properties').exists()) {
39 | hasLocalFile = true
40 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
41 | }
42 | user = hasLocalFile ? properties.getProperty("bintray.user") : ""
43 | key = hasLocalFile ? properties.getProperty("bintray.apikey") : ""
44 |
45 | publications = ['bintray']
46 | pkg {
47 | repo = "smartcompiler"
48 | name = "router-compiler"
49 | websiteUrl = 'https://github.com/kongpengcheng/SmartRoute'
50 | vcsUrl = 'https://github.com/kongpengcheng/SmartRoute.git'
51 | desc = "Annotation compiler for Router library."
52 | labels = ["Android", "Router", "annotation", "compiler"]
53 | licenses = ["Apache-2.0"]
54 | publicDownloadNumbers = true
55 | publish = true
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/matcher/AbsMatcher.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router.matcher;
2 |
3 | import android.net.Uri;
4 | import android.os.Bundle;
5 | import android.support.annotation.NonNull;
6 |
7 |
8 | import com.smart.router.router.RouteRequest;
9 |
10 | import java.util.Iterator;
11 | import java.util.List;
12 | import java.util.Set;
13 |
14 | /**
15 | * Abstract matcher.
16 | *
17 | * Created by chenenyu on 2016/12/23.
18 | */
19 | public abstract class AbsMatcher implements Matcher {
20 | /**
21 | * Priority in matcher list.
22 | */
23 | private int priority = 10;
24 |
25 | public AbsMatcher(int priority) {
26 | this.priority = priority;
27 | }
28 |
29 | protected void parseParams(Uri uri, RouteRequest routeRequest) {
30 | if (uri.getQuery() != null) {
31 | Bundle bundle = routeRequest.getExtras();
32 | if (bundle == null) {
33 | bundle = new Bundle();
34 | routeRequest.setExtras(bundle);
35 | }
36 |
37 | Set keys = uri.getQueryParameterNames();
38 | Iterator keyIterator = keys.iterator();
39 | while (keyIterator.hasNext()) {
40 | String key = keyIterator.next();
41 | List values = uri.getQueryParameters(key);
42 | if (values.size() > 1) {
43 | bundle.putStringArray(key, values.toArray(new String[0]));
44 | } else if (values.size() == 1) {
45 | bundle.putString(key, values.get(0));
46 | }
47 | }
48 | }
49 | }
50 |
51 | /**
52 | * {@link android.text.TextUtils#isEmpty(CharSequence)}.
53 | */
54 | protected boolean isEmpty(CharSequence str) {
55 | return str == null || str.length() == 0;
56 | }
57 |
58 | @Override
59 | public int compareTo(@NonNull Matcher matcher) {
60 | if (this == matcher) {
61 | return 0;
62 | }
63 | if (matcher instanceof AbsMatcher) {
64 | if (this.priority > ((AbsMatcher) matcher).priority) {
65 | return -1;
66 | } else {
67 | return 1;
68 | }
69 | }
70 | return matcher.compareTo(this);
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/router/publish.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.jfrog.bintray'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 |
4 | Properties config = new Properties()
5 | config.load(project.file('../VERSION.properties').newDataInputStream())
6 | def VERSION = config.getProperty("ROUTER_VERSION")
7 | group = "com.kong.router"
8 | version = VERSION
9 |
10 | def siteUrl = 'https://github.com/kongpengcheng/SmartRoute'
11 | def issuesUrl = 'https://github.com/kongpengcheng/SmartRoute.git'
12 | def gitUrl = 'https://github.com/kongpengcheng/SmartRoute.git'
13 |
14 | install {
15 | repositories.mavenInstaller.pom.project {
16 | packaging 'jar'
17 | name 'SmartRouter'
18 | artifactId "router"
19 | description 'Simple and flexible router library for Android platform.'
20 | url siteUrl
21 |
22 | licenses {
23 | license {
24 | name 'The Apache Software License, Version 2.0'
25 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
26 | }
27 | }
28 | developers {
29 | developer {
30 | id 'chenenyu'
31 | name 'chenenyu'
32 | email 'ceychina@gmail.com'
33 | }
34 | }
35 | }
36 | }
37 |
38 | task jar(type: Jar) {
39 | from android.sourceSets.main.java.srcDirs
40 | }
41 |
42 | task sourcesJar(type: Jar) {
43 | from android.sourceSets.main.java.srcDirs
44 | classifier = 'sources'
45 | }
46 |
47 | task javadoc(type: Javadoc) {
48 | options.encoding = 'UTF-8'
49 | source = android.sourceSets.main.java.srcDirs
50 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
51 | failOnError false
52 | }
53 |
54 | task javadocJar(type: Jar, dependsOn: javadoc) {
55 | from javadoc.getDestinationDir()
56 | classifier = 'javadoc'
57 | }
58 |
59 | artifacts {
60 | archives javadocJar
61 | archives sourcesJar
62 | }
63 |
64 | bintray {
65 | Properties properties = new Properties()
66 | boolean hasLocalFile = false
67 | if (project.rootProject.file('local.properties').exists()) {
68 | hasLocalFile = true
69 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
70 | }
71 | user = hasLocalFile ? properties.getProperty("bintray.user") : ""
72 | key = hasLocalFile ? properties.getProperty("bintray.apikey") : ""
73 |
74 | configurations = ['archives']
75 | pkg {
76 | repo = "smartrouter"
77 | name = "router"
78 | websiteUrl = 'https://github.com/kongpengcheng/SmartRoute'
79 | vcsUrl = 'https://github.com/kongpengcheng/SmartRoute.git'
80 | desc = "Annotation compiler for SmartRouter library."
81 | labels = ["Android", "SmartRouter", "annotation", "compiler"]
82 | licenses = ["Apache-2.0"]
83 | publicDownloadNumbers = true
84 | publish = true
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/matcher/SchemeMatcher.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router.matcher;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.support.annotation.Nullable;
6 |
7 | import com.smart.router.router.RouteRequest;
8 |
9 |
10 | /**
11 | * Standard scheme matcher. It matches scheme, authority(host, port) and path(if offered),
12 | * then transfers the query part(if offered) to bundle/arguments.
13 | *
14 | * If you configured a route like this:
15 | *
16 | *
17 | * -> @Route("http://example.com/user")
18 | *
19 | *
20 | * Then http://example.com/user will match this route,
21 | * http://example.com/user?id=9527&status=0 also does and puts bundles for you:
22 | *
23 | *
24 | * bundle.putString("id", "9527");
25 | *
26 | * bundle.putString("status", "0");
27 | *
28 | * intent.putExtras(bundle); or fragment.setArguments(bundle);
29 | *
30 | *
31 | *
32 | */
33 | public class SchemeMatcher extends AbsExplicitMatcher {
34 | public SchemeMatcher(int priority) {
35 | super(priority);
36 | }
37 |
38 | @Override
39 | public boolean match(Context context, Uri uri, @Nullable String route, RouteRequest routeRequest) {
40 | if (isEmpty(route)) {
41 | return false;
42 | }
43 | Uri routeUri = Uri.parse(route);
44 | if (uri.isAbsolute() && routeUri.isAbsolute()) { // scheme != null
45 | if (!uri.getScheme().equals(routeUri.getScheme())) {
46 | // http != https
47 | return false;
48 | }
49 | if (isEmpty(uri.getAuthority()) && isEmpty(routeUri.getAuthority())) {
50 | // host1 == host2 == empty
51 | return true;
52 | }
53 | // google.com == google.com:443 (include port)
54 | if (!isEmpty(uri.getAuthority()) && !isEmpty(routeUri.getAuthority())
55 | && uri.getAuthority().equals(routeUri.getAuthority())) {
56 | if (!cutSlash(uri.getPath()).equals(cutSlash(routeUri.getPath()))) {
57 | return false;
58 | }
59 |
60 | // bundle parser
61 | if (uri.getQuery() != null) {
62 | parseParams(uri, routeRequest);
63 | }
64 | return true;
65 | }
66 | }
67 | return false;
68 | }
69 |
70 | /**
71 | * 剔除path头部和尾部的斜杠/
72 | *
73 | * @param path 路径
74 | * @return 无/的路径
75 | */
76 | private String cutSlash(String path) {
77 | if (path.startsWith("/")) {
78 | return cutSlash(path.substring(1));
79 | }
80 | if (path.endsWith("/")) {
81 | return cutSlash(path.substring(0, path.length() - 1));
82 | }
83 | return path;
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/IRouter.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.os.Bundle;
7 | import android.os.PersistableBundle;
8 | import android.support.annotation.AnimRes;
9 | import android.support.annotation.RequiresApi;
10 | import android.support.v4.app.ActivityOptionsCompat;
11 | import android.support.v4.app.Fragment;
12 |
13 | /**
14 | * Router interface.
15 | *
16 | * Created by Harry.Kong.
17 | */
18 | public interface IRouter {
19 | IRouter build(Uri uri);
20 |
21 | IRouter callback(RouteCallback callback);
22 |
23 | /**
24 | * Call startActivityForResult.
25 | */
26 | IRouter requestCode(int requestCode);
27 |
28 | /**
29 | * @see Bundle#putAll(Bundle)
30 | */
31 | IRouter with(Bundle bundle);
32 |
33 | /**
34 | * @see Bundle#putAll(PersistableBundle)
35 | */
36 | @RequiresApi(21)
37 | IRouter with(PersistableBundle bundle);
38 |
39 | /**
40 | * bundle.putXXX(String key, XXX value).
41 | */
42 | IRouter with(String key, Object value);
43 |
44 | /**
45 | * @see Intent#addFlags(int)
46 | */
47 | IRouter addFlags(int flags);
48 |
49 | /**
50 | * @see Intent#setData(Uri)
51 | */
52 | IRouter setData(Uri data);
53 |
54 | /**
55 | * @see Intent#setType(String)
56 | */
57 | IRouter setType(String type);
58 |
59 | /**
60 | * @see Intent#setDataAndType(Uri, String)
61 | */
62 | IRouter setDataAndType(Uri data, String type);
63 |
64 | /**
65 | * @see Intent#setAction(String)
66 | */
67 | IRouter setAction(String action);
68 |
69 | /**
70 | * @see android.app.Activity#overridePendingTransition(int, int)
71 | */
72 | IRouter anim(@AnimRes int enterAnim, @AnimRes int exitAnim);
73 |
74 | /**
75 | * {@link ActivityOptionsCompat}.
76 | */
77 | IRouter activityOptions(ActivityOptionsCompat activityOptions);
78 |
79 | /**
80 | * Skip all the interceptors.
81 | */
82 | IRouter skipInterceptors();
83 |
84 | /**
85 | * Skip the named interceptors.
86 | */
87 | IRouter skipInterceptors(String... interceptors);
88 |
89 | /**
90 | * Add interceptors temporarily for current route request.
91 | */
92 | IRouter addInterceptors(String... interceptors);
93 |
94 | Intent getIntent(Context context);
95 |
96 | Object getFragment(Context context);
97 |
98 | void go(Context context, RouteCallback callback);
99 |
100 | void go(Context context);
101 |
102 | void go(Fragment fragment, RouteCallback callback);
103 |
104 | void go(Fragment fragment);
105 |
106 | void go(android.app.Fragment fragment, RouteCallback callback);
107 |
108 | void go(android.app.Fragment fragment);
109 | }
110 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/SmartRouter.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import android.net.Uri;
4 |
5 |
6 | import com.smart.router.router.matcher.AbsMatcher;
7 | import com.smart.router.router.util.RLog;
8 |
9 | import java.util.ArrayList;
10 | import java.util.List;
11 |
12 | /**
13 | * Entry class.
14 | *
15 | * Created by Harry.Kong.
16 | */
17 | public class SmartRouter {
18 | /**
19 | * You can get the raw uri in target page by call intent.getStringExtra(SmartRouter.RAW_URI).
20 | */
21 | public static final String RAW_URI = "raw_uri";
22 |
23 | private static List sGlobalInterceptors = new ArrayList<>();
24 |
25 |
26 | public static void initialize(Configuration configuration) {
27 | RLog.showLog(configuration.debuggable);
28 | AptHub.registerModules(configuration.modules);
29 | }
30 |
31 | public static IRouter build(String path) {
32 | return build(path == null ? null : Uri.parse(path));
33 | }
34 |
35 | public static IRouter build(Uri uri) {
36 | return RealRouter.getInstance().build(uri);
37 | }
38 |
39 | /**
40 | * Use {@link #handleRouteTable(RouteTable)} instead.
41 | *
42 | * This method will be removed in a future release.
43 | */
44 | @Deprecated
45 | public static void addRouteTable(RouteTable routeTable) {
46 | handleRouteTable(routeTable);
47 | }
48 |
49 | /**
50 | * Custom route table.
51 | */
52 | public static void handleRouteTable(RouteTable routeTable) {
53 | RealRouter.getInstance().handleRouteTable(routeTable);
54 | }
55 |
56 | /**
57 | * Custom interceptor table.
58 | */
59 | public static void handleInterceptorTable(InterceptorTable interceptorTable) {
60 | RealRouter.getInstance().handleInterceptorTable(interceptorTable);
61 | }
62 |
63 | /**
64 | * Custom targets' interceptors.
65 | */
66 | public static void handleTargetInterceptors(TargetInterceptors targetInterceptors) {
67 | RealRouter.getInstance().handleTargetInterceptors(targetInterceptors);
68 | }
69 |
70 | /**
71 | * Auto inject params from bundle.
72 | *
73 | * @param obj Instance of Activity or Fragment.
74 | */
75 | public static void injectParams(Object obj) {
76 | RealRouter.getInstance().injectParams(obj);
77 | }
78 |
79 | /**
80 | * Global interceptor.
81 | */
82 | public static void addGlobalInterceptor(RouteInterceptor routeInterceptor) {
83 | sGlobalInterceptors.add(routeInterceptor);
84 | }
85 |
86 | public static List getGlobalInterceptors() {
87 | return sGlobalInterceptors;
88 | }
89 |
90 | /**
91 | * Register your own matcher.
92 | *
93 | */
94 | public static void registerMatcher(AbsMatcher matcher) {
95 | MatcherRegistry.register(matcher);
96 | }
97 |
98 | public static void clearMatcher() {
99 | MatcherRegistry.clear();
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SmartRoute
2 | **github:https://github.com/kongpengcheng/SmartRoute**
3 |
4 | **使用方式**
5 |
6 | <1>`首先需要在module 和app 的gradle 的defaultConfig中添加下面代码(ps:注解生成器中我需要每个模块的名字)`
7 |
8 |
9 | javaCompileOptions {
10 | annotationProcessorOptions {
11 | arguments = ["moduleName": project.name]
12 | }
13 | }
14 |
15 |
16 |
17 |
18 | <2>`其次需要在你需要的模块中添加两行依赖`
19 |
20 |
21 | 1. compile 'com.kong.router:router:1.1.3'
22 | 2. annotationProcessor 'com.kong.router:compiler:1.1.2'
23 |
24 | ----------
25 | **背景**
26 |
27 | - gradle升级到3.0以前的apt已经不支持(ps:apt已经很早就停止维护),现在项目注解必须使用annotationProcessor ,其中切换过程遇到很多坑,3.0改版变化太大,其中有想学习编写gradle我推荐一本action系列的书《实战Gradle》。
28 | - 上传jcenter注解优化到每个模块依赖,项目不需要依赖。
29 | - 查看大量框架查看(ps:阿里的ARouter,google的outoserver),这个框架的实现原理和google不一样google采用的下发json来维护,此框架映射采用map进行维护路由表。
30 |
31 | **路由实现的意义**
32 |
33 | 1.在一些复杂的业务场景下(比如商城),灵活性比较强,很多功能都是运营人员动态配置的,比如下发一个活动页面,我们事先并不知道具体的目标页面,但如果事先做了约定,提前做好页面映射,便可以自由配置跳转。
34 |
35 | 随着业务量的增长,客户端必然随之膨胀,开发人员的工作量越来越大,比如64K问题,比如协作开发问题。App一般都会走向组件化、插件化的道路,而组件化、插件化的前提就是解耦,那么我们首先要做的就是解耦页面之间的依赖关系。
36 |
37 |
38 | 1.添加注解
39 | > @Route("test")
40 | public class TestActivity extends AppCompatActivity {
41 | @Override
42 | protected void onCreate(Bundle savedInstanceState) {
43 | super.onCreate(savedInstanceState);
44 | setContentView(R.layout.activity_test);
45 | initView();
46 | SmartRouter.injectParams(this);
47 | }
48 | 2.实现页面跳转
49 | ```
50 | SmartRouter.build("test").go(this);
51 | ```
52 |
53 | 3.实现页面跳转加回调
54 |
55 | > SmartRouter.build("test").callback(new RouteCallback() { // 添加结果回调
56 | @Override
57 | public void callback(RouteResult state, Uri uri, String message) {
58 | if (state == RouteResult.SUCCEED) {
59 | Toast.makeText(MainActivity.this, "succeed: " + uri.toString(), Toast.LENGTH_SHORT).show();
60 | } else {
61 | Toast.makeText(MainActivity.this, "error: " + uri + ", " + message, Toast.LENGTH_SHORT).show();
62 | }
63 | }
64 | }).go(this);
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | 4.携带参数进行跳转
74 |
75 | > Bundle bundle = new Bundle();
76 | bundle.putString("param", "this is message from mainactivity");
77 | SmartRouter.build("param").with(bundle).go(this);
78 |
79 |
80 | 5.拦截功能(ps:假如界面需要检测是否登录,如果没登录先跳转到登录界面,首先创建拦截器,其次需要拦截检测的类注解)
81 |
82 | **拦截调用**
83 | ```
84 | SmartRouter.build("intercepted").addInterceptors("SampleInterceptor").go(this);
85 |
86 | ```
87 | **拦截取消**
88 | ```
89 | SmartRouter.build("intercepted").skipInterceptors("SampleInterceptor").go(this);
90 | ```
91 | 6.网页跳转原声app ,只需要拦截到uri手动给路由就ok
92 |
93 | > public class SchemeFilterActivity extends Activity {
94 | @Override
95 | protected void onCreate(@Nullable Bundle savedInstanceState) {
96 | super.onCreate(savedInstanceState);
97 | Uri uri = getIntent().getData();
98 | if (uri != null) {
99 | if (!"router://filter".equals(uri.toString())) {
100 | SmartRouter.build(uri).go(this);
101 | }
102 | finish();
103 | }
104 | }
105 | }
106 |
107 | 以上有任何问题或者有好的建议请加我qq:1106919334
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | 上传命令:
116 | 需要先在local.properties文件中配置如下信息:
117 | bintray.user=***
118 | bintray.apikey=***
119 | 配置完后在你那个SmartRouter工程目录下执行命令:gradlew bintrayUpload就OK了
120 |
121 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/AptHub.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 |
4 | import com.smart.router.router.util.RLog;
5 |
6 | import java.lang.reflect.Constructor;
7 | import java.util.HashMap;
8 | import java.util.Map;
9 |
10 | /**
11 | * Hub for 'apt' classes.
12 | *
13 | * Created by Harry.Kong.
14 | */
15 | class AptHub {
16 | private static final String PACKAGE_NAME = "com.smart.router.router";
17 | private static final String DOT = ".";
18 | private static final String ROUTE_TABLE = "RouteTable";
19 | private static final String INTERCEPTOR_TABLE = "InterceptorTable";
20 | private static final String TARGET_INTERCEPTORS = "TargetInterceptors";
21 |
22 | // Uri -> Activity/Fragment
23 | static Map> routeTable = new HashMap<>();
24 | // Activity/Fragment -> interceptorTable' name
25 | static Map, String[]> targetInterceptors = new HashMap<>();
26 | // interceptor's name -> interceptor
27 | static Map> interceptorTable = new HashMap<>();
28 | // injector's name -> injector
29 | static Map> injectors = new HashMap<>();
30 |
31 | /**
32 | * This method offers an ability to register extra modules for developers.
33 | *
34 | * @param modules extra modules' name
35 | */
36 | synchronized static void registerModules(String... modules) {
37 | if (modules == null || modules.length == 0) {
38 | RLog.w("empty modules.");
39 | } else {
40 | // validate module name first.
41 | validateModuleName(modules);
42 |
43 | /* RouteTable */
44 | String routeTableName;
45 | for (String module : modules) {
46 | try {
47 | routeTableName = PACKAGE_NAME + DOT + capitalize(module) + ROUTE_TABLE;
48 | Class> routeTableClz = Class.forName(routeTableName);
49 | Constructor constructor = routeTableClz.getConstructor();
50 | RouteTable instance = (RouteTable) constructor.newInstance();
51 | instance.handle(routeTable);
52 | } catch (ClassNotFoundException e) {
53 | RLog.i(String.format("There is no RouteTable in module: %s.", module));
54 | } catch (Exception e) {
55 | RLog.w(e.getMessage());
56 | }
57 | }
58 | RLog.i("RouteTable", routeTable.toString());
59 |
60 | /* TargetInterceptors */
61 | String targetInterceptorsName;
62 | for (String moduleName : modules) {
63 | try {
64 | targetInterceptorsName = PACKAGE_NAME + DOT + capitalize(moduleName) + TARGET_INTERCEPTORS;
65 | Class> clz = Class.forName(targetInterceptorsName);
66 | Constructor constructor = clz.getConstructor();
67 | TargetInterceptors instance = (TargetInterceptors) constructor.newInstance();
68 | instance.handle(targetInterceptors);
69 | } catch (ClassNotFoundException e) {
70 | RLog.i(String.format("There is no TargetInterceptors in module: %s.", moduleName));
71 | } catch (Exception e) {
72 | RLog.w(e.getMessage());
73 | }
74 | }
75 | if (!targetInterceptors.isEmpty()) {
76 | RLog.i("TargetInterceptors", targetInterceptors.toString());
77 | }
78 |
79 | /* InterceptorTable */
80 | String interceptorName;
81 | for (String moduleName : modules) {
82 | try {
83 | interceptorName = PACKAGE_NAME + DOT + capitalize(moduleName) + INTERCEPTOR_TABLE;
84 | Class> clz = Class.forName(interceptorName);
85 | Constructor constructor = clz.getConstructor();
86 | InterceptorTable instance = (InterceptorTable) constructor.newInstance();
87 | instance.handle(interceptorTable);
88 | } catch (ClassNotFoundException e) {
89 | RLog.i(String.format("There is no InterceptorTable in module: %s.", moduleName));
90 | } catch (Exception e) {
91 | RLog.w(e.getMessage());
92 | }
93 | }
94 | if (!interceptorTable.isEmpty()) {
95 | RLog.i("InterceptorTable", interceptorTable.toString());
96 | }
97 | }
98 | }
99 |
100 | private static String capitalize(CharSequence self) {
101 | return self.length() == 0 ? "" :
102 | "" + Character.toUpperCase(self.charAt(0)) + self.subSequence(1, self.length());
103 | }
104 |
105 | private static void validateModuleName(String... modules) {
106 | for (int i = 0; i < modules.length; i++) {
107 | modules[i] = modules[i].replace('.', '_').replace('-', '_');
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/RouteRequest.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import android.net.Uri;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.ActivityOptionsCompat;
7 |
8 | import java.io.Serializable;
9 | import java.util.Arrays;
10 | import java.util.HashSet;
11 | import java.util.Set;
12 |
13 | /**
14 | * Route request object.
15 | *
16 | * Created by Harry.Kong..
17 | */
18 | @SuppressWarnings("WeakerAccess")
19 | public class RouteRequest implements Serializable {
20 | private static final int INVALID_REQUEST_CODE = -1;
21 |
22 | private Uri uri;
23 | private Bundle extras;
24 | private int flags;
25 | private Uri data;
26 | private String type;
27 | private String action;
28 | // skip all the interceptors
29 | private boolean skipInterceptors;
30 | // skip some interceptors temporarily
31 | @Nullable
32 | private Set removedInterceptors;
33 | // add some interceptors temporarily
34 | @Nullable
35 | private Set addedInterceptors;
36 | @Nullable
37 | private RouteCallback callback;
38 | private int requestCode = INVALID_REQUEST_CODE;
39 | private int enterAnim;
40 | private int exitAnim;
41 | @Nullable
42 | private ActivityOptionsCompat activityOptionsCompat;
43 |
44 |
45 | public RouteRequest(Uri uri) {
46 | this.uri = uri;
47 | }
48 |
49 | public Uri getUri() {
50 | return uri;
51 | }
52 |
53 | public void setUri(Uri uri) {
54 | this.uri = uri;
55 | }
56 |
57 | public Bundle getExtras() {
58 | return extras;
59 | }
60 |
61 | public void setExtras(Bundle extras) {
62 | this.extras = extras;
63 | }
64 |
65 | public int getFlags() {
66 | return flags;
67 | }
68 |
69 | public void setFlags(int flags) {
70 | this.flags = flags;
71 | }
72 |
73 | public void addFlags(int flags) {
74 | this.flags |= flags;
75 | }
76 |
77 | public Uri getData() {
78 | return data;
79 | }
80 |
81 | public void setData(Uri data) {
82 | this.data = data;
83 | }
84 |
85 | public String getType() {
86 | return type;
87 | }
88 |
89 | public void setType(String type) {
90 | this.type = type;
91 | }
92 |
93 | public String getAction() {
94 | return action;
95 | }
96 |
97 | public void setAction(String action) {
98 | this.action = action;
99 | }
100 |
101 | public boolean isSkipInterceptors() {
102 | return skipInterceptors;
103 | }
104 |
105 | public void setSkipInterceptors(boolean skipInterceptors) {
106 | this.skipInterceptors = skipInterceptors;
107 | }
108 |
109 | @Nullable
110 | public Set getAddedInterceptors() {
111 | return addedInterceptors;
112 | }
113 |
114 | @Nullable
115 | public Set getRemovedInterceptors() {
116 | return removedInterceptors;
117 | }
118 |
119 | public void addInterceptors(String... interceptors) {
120 | if (interceptors == null || interceptors.length <= 0) {
121 | return;
122 | }
123 | if (this.addedInterceptors == null) {
124 | this.addedInterceptors = new HashSet<>(interceptors.length);
125 | }
126 | this.addedInterceptors.addAll(Arrays.asList(interceptors));
127 | }
128 |
129 | public void removeInterceptors(String... interceptors) {
130 | if (interceptors == null || interceptors.length <= 0) {
131 | return;
132 | }
133 | if (this.removedInterceptors == null) {
134 | this.removedInterceptors = new HashSet<>(interceptors.length);
135 | }
136 | this.removedInterceptors.addAll(Arrays.asList(interceptors));
137 | }
138 |
139 | @Nullable
140 | public RouteCallback getCallback() {
141 | return callback;
142 | }
143 |
144 | public void setCallback(@Nullable RouteCallback callback) {
145 | this.callback = callback;
146 | }
147 |
148 | public int getRequestCode() {
149 | return requestCode;
150 | }
151 |
152 | public void setRequestCode(int requestCode) {
153 | if (requestCode < 0) {
154 | this.requestCode = INVALID_REQUEST_CODE;
155 | } else {
156 | this.requestCode = requestCode;
157 | }
158 | }
159 |
160 | public int getEnterAnim() {
161 | return enterAnim;
162 | }
163 |
164 | public void setEnterAnim(int enterAnim) {
165 | this.enterAnim = enterAnim;
166 | }
167 |
168 | public int getExitAnim() {
169 | return exitAnim;
170 | }
171 |
172 | public void setExitAnim(int exitAnim) {
173 | this.exitAnim = exitAnim;
174 | }
175 |
176 | @Nullable
177 | public ActivityOptionsCompat getActivityOptionsCompat() {
178 | return activityOptionsCompat;
179 | }
180 |
181 | public void setActivityOptionsCompat(@Nullable ActivityOptionsCompat activityOptionsCompat) {
182 | this.activityOptionsCompat = activityOptionsCompat;
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/compiler/src/main/java/com/smart/router/compiler/processor/InterceptorProcessor.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.compiler.processor;
2 |
3 | import com.smart.router.annotation.Interceptor;
4 | import com.smart.router.compiler.util.Logger;
5 | import com.squareup.javapoet.ClassName;
6 | import com.squareup.javapoet.JavaFile;
7 | import com.squareup.javapoet.MethodSpec;
8 | import com.squareup.javapoet.ParameterSpec;
9 | import com.squareup.javapoet.ParameterizedTypeName;
10 | import com.squareup.javapoet.TypeSpec;
11 | import com.squareup.javapoet.WildcardTypeName;
12 |
13 | import java.io.IOException;
14 | import java.util.HashSet;
15 | import java.util.Map;
16 | import java.util.Set;
17 |
18 | import javax.annotation.processing.AbstractProcessor;
19 | import javax.annotation.processing.ProcessingEnvironment;
20 | import javax.annotation.processing.RoundEnvironment;
21 | import javax.annotation.processing.SupportedAnnotationTypes;
22 | import javax.annotation.processing.SupportedOptions;
23 | import javax.annotation.processing.SupportedSourceVersion;
24 | import javax.lang.model.SourceVersion;
25 | import javax.lang.model.element.Element;
26 | import javax.lang.model.element.Modifier;
27 | import javax.lang.model.element.TypeElement;
28 |
29 | import static com.smart.router.compiler.util.Consts.CLASS_JAVA_DOC;
30 | import static com.smart.router.compiler.util.Consts.HANDLE;
31 | import static com.smart.router.compiler.util.Consts.INTERCEPTOR_ANNOTATION_TYPE;
32 | import static com.smart.router.compiler.util.Consts.INTERCEPTOR_INTERFACE;
33 | import static com.smart.router.compiler.util.Consts.INTERCEPTOR_TABLE;
34 | import static com.smart.router.compiler.util.Consts.OPTION_MODULE_NAME;
35 | import static com.smart.router.compiler.util.Consts.PACKAGE_NAME;
36 |
37 | /**
38 | * Created by Harry.Kong.
39 | * Time 2017/11/8.
40 | * Description:annotation processor.
41 | */
42 | @SupportedAnnotationTypes(INTERCEPTOR_ANNOTATION_TYPE)
43 | @SupportedOptions(OPTION_MODULE_NAME)
44 | @SupportedSourceVersion(SourceVersion.RELEASE_7)
45 | public class InterceptorProcessor extends AbstractProcessor {
46 | private String mModuleName;
47 | private Logger mLogger;
48 |
49 | @Override
50 | public synchronized void init(ProcessingEnvironment processingEnvironment) {
51 | super.init(processingEnvironment);
52 | mModuleName = processingEnvironment.getOptions().get(OPTION_MODULE_NAME);
53 | mLogger = new Logger(processingEnvironment.getMessager());
54 | }
55 |
56 | @Override
57 | public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
58 | Set extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Interceptor.class);
59 | if (elements == null || elements.isEmpty()) {
60 | return true;
61 | }
62 | mLogger.info(String.format(">>> %s: InterceptorProcessor begin... <<<", mModuleName));
63 | // 合法的TypeElement集合
64 | Set typeElements = new HashSet<>();
65 | for (Element element : elements) {
66 | if (validateElement(element)) {
67 | typeElements.add((TypeElement) element);
68 | } else {
69 | mLogger.error(element, String.format("The annotated element is not a implementation class of %s",
70 | INTERCEPTOR_INTERFACE));
71 | }
72 | }
73 |
74 | if (mModuleName != null) {
75 | String validModuleName = mModuleName.replace(".", "_").replace("-", "_");
76 | generateInterceptors(validModuleName, typeElements);
77 | } else {
78 | throw new RuntimeException(String.format("No option `%s` passed to Interceptor annotation processor.", OPTION_MODULE_NAME));
79 | }
80 | mLogger.info(String.format(">>> %s: InterceptorProcessor end. <<<", mModuleName));
81 | return true;
82 | }
83 |
84 | private boolean validateElement(Element element) {
85 | return element.getKind().isClass() && processingEnv.getTypeUtils().isAssignable(element.asType(),
86 | processingEnv.getElementUtils().getTypeElement(INTERCEPTOR_INTERFACE).asType());
87 | }
88 |
89 | private void generateInterceptors(String moduleName, Set elements) {
90 | /*
91 | * params
92 | */
93 | TypeElement interceptorType = processingEnv.getElementUtils().getTypeElement(INTERCEPTOR_INTERFACE);
94 | // Map> map
95 | ParameterizedTypeName mapTypeName = ParameterizedTypeName.get(ClassName.get(Map.class),
96 | ClassName.get(String.class), ParameterizedTypeName.get(ClassName.get(Class.class),
97 | WildcardTypeName.subtypeOf(ClassName.get(interceptorType))));
98 | ParameterSpec mapParameterSpec = ParameterSpec.builder(mapTypeName, "map").build();
99 | /*
100 | * method
101 | */
102 | MethodSpec.Builder handleInterceptors = MethodSpec.methodBuilder(HANDLE)
103 | .addAnnotation(Override.class)
104 | .addModifiers(Modifier.PUBLIC)
105 | .addParameter(mapParameterSpec);
106 | for (TypeElement element : elements) {
107 | mLogger.info(String.format("Found interceptor: %s", element.getQualifiedName()));
108 | Interceptor interceptor = element.getAnnotation(Interceptor.class);
109 | String name = interceptor.value();
110 | handleInterceptors.addStatement("map.put($S, $T.class)", name, ClassName.get(element));
111 | }
112 |
113 | /*
114 | * class
115 | */
116 | TypeSpec type = TypeSpec.classBuilder(capitalize(moduleName) + INTERCEPTOR_TABLE)
117 | .addSuperinterface(ClassName.get(PACKAGE_NAME, INTERCEPTOR_TABLE))
118 | .addModifiers(Modifier.PUBLIC)
119 | .addMethod(handleInterceptors.build())
120 | .addJavadoc(CLASS_JAVA_DOC)
121 | .build();
122 |
123 | try {
124 | JavaFile.builder(PACKAGE_NAME, type).build().writeTo(processingEnv.getFiler());
125 | } catch (IOException e) {
126 | e.printStackTrace();
127 | }
128 | }
129 |
130 | private String capitalize(CharSequence self) {
131 | return self.length() == 0 ? "" :
132 | "" + Character.toUpperCase(self.charAt(0)) + self.subSequence(1, self.length());
133 | }
134 |
135 | }
136 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/AbsRouter.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import android.os.IBinder;
8 | import android.os.Parcelable;
9 | import android.os.PersistableBundle;
10 | import android.support.annotation.AnimRes;
11 | import android.support.annotation.RequiresApi;
12 | import android.support.v4.app.ActivityOptionsCompat;
13 | import android.support.v4.app.Fragment;
14 | import android.util.SparseArray;
15 |
16 |
17 | import com.smart.router.router.util.RLog;
18 |
19 | import java.io.Serializable;
20 | import java.util.ArrayList;
21 |
22 | /**
23 | * Help to construct a {@link RouteRequest}.
24 | *
25 | * Created by Harry.Kong.
26 | */
27 | abstract class AbsRouter implements IRouter {
28 | RouteRequest mRouteRequest;
29 |
30 | @Override
31 | public IRouter build(Uri uri) {
32 | mRouteRequest = new RouteRequest(uri);
33 | Bundle bundle = new Bundle();
34 | bundle.putString(SmartRouter.RAW_URI, uri == null ? null : uri.toString());
35 | mRouteRequest.setExtras(bundle);
36 | return this;
37 | }
38 |
39 | @Override
40 | public IRouter callback(RouteCallback callback) {
41 | mRouteRequest.setCallback(callback);
42 | return this;
43 | }
44 |
45 | @Override
46 | public IRouter requestCode(int requestCode) {
47 | mRouteRequest.setRequestCode(requestCode);
48 | return this;
49 | }
50 |
51 | @Override
52 | public IRouter with(Bundle bundle) {
53 | if (bundle != null && !bundle.isEmpty()) {
54 | Bundle extras = mRouteRequest.getExtras();
55 | if (extras == null) {
56 | extras = new Bundle();
57 | }
58 | extras.putAll(bundle);
59 | mRouteRequest.setExtras(extras);
60 | }
61 | return this;
62 | }
63 |
64 | @RequiresApi(21)
65 | @Override
66 | public IRouter with(PersistableBundle bundle) {
67 | if (bundle != null && !bundle.isEmpty()) {
68 | Bundle extras = mRouteRequest.getExtras();
69 | if (extras == null) {
70 | extras = new Bundle();
71 | }
72 | extras.putAll(bundle);
73 | mRouteRequest.setExtras(extras);
74 | }
75 | return this;
76 | }
77 |
78 | @SuppressWarnings("unchecked")
79 | @Override
80 | public IRouter with(String key, Object value) {
81 | if (value == null) {
82 | RLog.w("Ignored: The extra value is null.");
83 | return this;
84 | }
85 | Bundle bundle = mRouteRequest.getExtras();
86 | if (bundle == null) {
87 | bundle = new Bundle();
88 | }
89 | if (value instanceof Bundle) {
90 | bundle.putBundle(key, (Bundle) value);
91 | } else if (value instanceof Byte) {
92 | bundle.putByte(key, (byte) value);
93 | } else if (value instanceof Short) {
94 | bundle.putShort(key, (short) value);
95 | } else if (value instanceof Integer) {
96 | bundle.putInt(key, (int) value);
97 | } else if (value instanceof Long) {
98 | bundle.putLong(key, (long) value);
99 | } else if (value instanceof Character) {
100 | bundle.putChar(key, (char) value);
101 | } else if (value instanceof Boolean) {
102 | bundle.putBoolean(key, (boolean) value);
103 | } else if (value instanceof Float) {
104 | bundle.putFloat(key, (float) value);
105 | } else if (value instanceof Double) {
106 | bundle.putDouble(key, (double) value);
107 | } else if (value instanceof String) {
108 | bundle.putString(key, (String) value);
109 | } else if (value instanceof CharSequence) {
110 | bundle.putCharSequence(key, (CharSequence) value);
111 | } else if (value instanceof byte[]) {
112 | bundle.putByteArray(key, (byte[]) value);
113 | } else if (value instanceof short[]) {
114 | bundle.putShortArray(key, (short[]) value);
115 | } else if (value instanceof int[]) {
116 | bundle.putIntArray(key, (int[]) value);
117 | } else if (value instanceof long[]) {
118 | bundle.putLongArray(key, (long[]) value);
119 | } else if (value instanceof char[]) {
120 | bundle.putCharArray(key, (char[]) value);
121 | } else if (value instanceof boolean[]) {
122 | bundle.putBooleanArray(key, (boolean[]) value);
123 | } else if (value instanceof float[]) {
124 | bundle.putFloatArray(key, (float[]) value);
125 | } else if (value instanceof double[]) {
126 | bundle.putDoubleArray(key, (double[]) value);
127 | } else if (value instanceof String[]) {
128 | bundle.putStringArray(key, (String[]) value);
129 | } else if (value instanceof CharSequence[]) {
130 | bundle.putCharSequenceArray(key, (CharSequence[]) value);
131 | } else if (value instanceof IBinder) {
132 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
133 | bundle.putBinder(key, (IBinder) value);
134 | } else {
135 | RLog.e("putBinder() requires api 18.");
136 | }
137 | } else if (value instanceof ArrayList) {
138 | if (!((ArrayList) value).isEmpty()) {
139 | Object obj = ((ArrayList) value).get(0);
140 | if (obj instanceof Integer) {
141 | bundle.putIntegerArrayList(key, (ArrayList) value);
142 | } else if (obj instanceof String) {
143 | bundle.putStringArrayList(key, (ArrayList) value);
144 | } else if (obj instanceof CharSequence) {
145 | bundle.putCharSequenceArrayList(key, (ArrayList) value);
146 | } else if (obj instanceof Parcelable) {
147 | bundle.putParcelableArrayList(key, (ArrayList extends Parcelable>) value);
148 | }
149 | }
150 | } else if (value instanceof SparseArray) {
151 | bundle.putSparseParcelableArray(key, (SparseArray extends Parcelable>) value);
152 | } else if (value instanceof Parcelable) {
153 | bundle.putParcelable(key, (Parcelable) value);
154 | } else if (value instanceof Parcelable[]) {
155 | bundle.putParcelableArray(key, (Parcelable[]) value);
156 | } else if (value instanceof Serializable) {
157 | bundle.putSerializable(key, (Serializable) value);
158 | } else {
159 | RLog.w("Unknown object type.");
160 | }
161 | mRouteRequest.setExtras(bundle);
162 | return this;
163 | }
164 |
165 | @Override
166 | public IRouter addFlags(int flags) {
167 | mRouteRequest.addFlags(flags);
168 | return this;
169 | }
170 |
171 | @Override
172 | public IRouter setData(Uri data) {
173 | mRouteRequest.setData(data);
174 | return this;
175 | }
176 |
177 | @Override
178 | public IRouter setType(String type) {
179 | mRouteRequest.setType(type);
180 | return this;
181 | }
182 |
183 | @Override
184 | public IRouter setDataAndType(Uri data, String type) {
185 | mRouteRequest.setData(data);
186 | mRouteRequest.setType(type);
187 | return this;
188 | }
189 |
190 | @Override
191 | public IRouter setAction(String action) {
192 | mRouteRequest.setAction(action);
193 | return this;
194 | }
195 |
196 | @Override
197 | public IRouter anim(@AnimRes int enterAnim, @AnimRes int exitAnim) {
198 | mRouteRequest.setEnterAnim(enterAnim);
199 | mRouteRequest.setExitAnim(exitAnim);
200 | return this;
201 | }
202 |
203 | @Override
204 | public IRouter activityOptions(ActivityOptionsCompat activityOptions) {
205 | mRouteRequest.setActivityOptionsCompat(activityOptions);
206 | return this;
207 | }
208 |
209 | @Override
210 | public IRouter skipInterceptors() {
211 | mRouteRequest.setSkipInterceptors(true);
212 | return this;
213 | }
214 |
215 | @Override
216 | public IRouter skipInterceptors(String... interceptors) {
217 | mRouteRequest.removeInterceptors(interceptors);
218 | return this;
219 | }
220 |
221 | @Override
222 | public IRouter addInterceptors(String... interceptors) {
223 | mRouteRequest.addInterceptors(interceptors);
224 | return this;
225 | }
226 |
227 | @Override
228 | public void go(Context context, RouteCallback callback) {
229 | mRouteRequest.setCallback(callback);
230 | go(context);
231 | }
232 |
233 | @Override
234 | public void go(Fragment fragment, RouteCallback callback) {
235 | mRouteRequest.setCallback(callback);
236 | go(fragment);
237 | }
238 |
239 | @Override
240 | public void go(android.app.Fragment fragment, RouteCallback callback) {
241 | mRouteRequest.setCallback(callback);
242 | go(fragment);
243 | }
244 | }
245 |
--------------------------------------------------------------------------------
/compiler/src/main/java/com/smart/router/compiler/processor/RouteProcessor.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.compiler.processor;
2 |
3 | import com.smart.router.annotation.Route;
4 | import com.smart.router.compiler.util.Logger;
5 | import com.squareup.javapoet.ClassName;
6 | import com.squareup.javapoet.JavaFile;
7 | import com.squareup.javapoet.MethodSpec;
8 | import com.squareup.javapoet.ParameterSpec;
9 | import com.squareup.javapoet.ParameterizedTypeName;
10 | import com.squareup.javapoet.TypeName;
11 | import com.squareup.javapoet.TypeSpec;
12 | import com.squareup.javapoet.WildcardTypeName;
13 |
14 | import java.io.IOException;
15 | import java.util.HashSet;
16 | import java.util.Map;
17 | import java.util.Set;
18 |
19 | import javax.annotation.processing.AbstractProcessor;
20 | import javax.annotation.processing.ProcessingEnvironment;
21 | import javax.annotation.processing.RoundEnvironment;
22 | import javax.annotation.processing.SupportedAnnotationTypes;
23 | import javax.annotation.processing.SupportedOptions;
24 | import javax.annotation.processing.SupportedSourceVersion;
25 | import javax.lang.model.SourceVersion;
26 | import javax.lang.model.element.Element;
27 | import javax.lang.model.element.Modifier;
28 | import javax.lang.model.element.TypeElement;
29 |
30 | import static com.smart.router.compiler.util.Consts.ACTIVITY_FULL_NAME;
31 | import static com.smart.router.compiler.util.Consts.CLASS_JAVA_DOC;
32 | import static com.smart.router.compiler.util.Consts.FRAGMENT_FULL_NAME;
33 | import static com.smart.router.compiler.util.Consts.FRAGMENT_V4_FULL_NAME;
34 | import static com.smart.router.compiler.util.Consts.HANDLE;
35 | import static com.smart.router.compiler.util.Consts.OPTION_MODULE_NAME;
36 | import static com.smart.router.compiler.util.Consts.PACKAGE_NAME;
37 | import static com.smart.router.compiler.util.Consts.ROUTE_ANNOTATION_TYPE;
38 | import static com.smart.router.compiler.util.Consts.ROUTE_TABLE;
39 | import static com.smart.router.compiler.util.Consts.ROUTE_TABLE_FULL_NAME;
40 | import static com.smart.router.compiler.util.Consts.TABLE_INTERCEPTORS;
41 |
42 | /**
43 | * Created by Harry.Kong.
44 | * Time 2017/11/8.
45 | * Description:annotation processor.
46 | */
47 | @SupportedAnnotationTypes(ROUTE_ANNOTATION_TYPE)
48 | @SupportedOptions(OPTION_MODULE_NAME)
49 | @SupportedSourceVersion(SourceVersion.RELEASE_7)
50 | public class RouteProcessor extends AbstractProcessor {
51 | private String mModuleName;
52 | private Logger mLogger;
53 |
54 | @Override
55 | public synchronized void init(ProcessingEnvironment processingEnvironment) {
56 | super.init(processingEnvironment);
57 | mModuleName = processingEnvironment.getOptions().get(OPTION_MODULE_NAME);
58 | mLogger = new Logger(processingEnvironment.getMessager());
59 | }
60 |
61 | @Override
62 | public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
63 | Set extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Route.class);
64 | if (elements == null || elements.isEmpty()) {
65 | return true;
66 | }
67 | mLogger.info(String.format(">>> %s: RouteProcessor begin... <<<", mModuleName));
68 | // 合法的TypeElement集合
69 | Set typeElements = new HashSet<>();
70 | for (Element element : elements) {
71 | if (validateElement(element)) {
72 | typeElements.add((TypeElement) element);
73 | }
74 | }
75 | if (mModuleName != null) {
76 | String validModuleName = mModuleName.replace(".", "_").replace("-", "_");
77 | generateRouteTable(validModuleName, typeElements);
78 | generateTargetInterceptors(validModuleName, typeElements);
79 | } else {
80 | throw new RuntimeException(String.format("No option `%s` passed to Route annotation processor.", OPTION_MODULE_NAME));
81 | }
82 | mLogger.info(String.format(">>> %s: RouteProcessor end. <<<", mModuleName));
83 | return true;
84 | }
85 |
86 | /**
87 | * Verify the annotated class. Must be a subtype of Activity or Fragment.
88 | */
89 | private boolean validateElement(Element typeElement) {
90 | if (!isSubtype(typeElement, ACTIVITY_FULL_NAME) && !isSubtype(typeElement, FRAGMENT_V4_FULL_NAME)
91 | && !isSubtype(typeElement, FRAGMENT_FULL_NAME)) {
92 | mLogger.error(typeElement, String.format("%s is not a subclass of Activity or Fragment.",
93 | typeElement.getSimpleName().toString()));
94 | return false;
95 | }
96 | Set modifiers = typeElement.getModifiers();
97 | // abstract class.
98 | if (modifiers.contains(Modifier.ABSTRACT)) {
99 | mLogger.error(typeElement, String.format("The class %s is abstract. You can't annotate abstract classes with @%s.",
100 | ((TypeElement) typeElement).getQualifiedName(), Route.class.getSimpleName()));
101 | return false;
102 | }
103 | return true;
104 | }
105 |
106 | private boolean isSubtype(Element typeElement, String type) {
107 | return processingEnv.getTypeUtils().isSubtype(typeElement.asType(),
108 | processingEnv.getElementUtils().getTypeElement(type).asType());
109 | }
110 |
111 | /**
112 | * RouteTable.
113 | */
114 | private void generateRouteTable(String moduleName, Set elements) {
115 | // Map> map
116 | ParameterizedTypeName mapTypeName = ParameterizedTypeName.get(ClassName.get(Map.class),
117 | ClassName.get(String.class), ParameterizedTypeName.get(ClassName.get(Class.class),
118 | WildcardTypeName.subtypeOf(Object.class)));
119 | ParameterSpec mapParameterSpec = ParameterSpec.builder(mapTypeName, "map").build();
120 |
121 | MethodSpec.Builder methodHandle = MethodSpec.methodBuilder(HANDLE)
122 | .addAnnotation(Override.class)
123 | .addModifiers(Modifier.PUBLIC)
124 | .addParameter(mapParameterSpec);
125 | for (TypeElement element : elements) {
126 | mLogger.info(String.format("Found routed target: %s", element.getQualifiedName()));
127 | Route route = element.getAnnotation(Route.class);
128 | String[] paths = route.value();
129 | for (String path : paths) {
130 | methodHandle.addStatement("map.put($S, $T.class)", path, ClassName.get(element));
131 | }
132 | }
133 |
134 | TypeElement interfaceType = processingEnv.getElementUtils().getTypeElement(ROUTE_TABLE_FULL_NAME);
135 | TypeSpec type = TypeSpec.classBuilder(capitalize(moduleName) + ROUTE_TABLE)
136 | .addSuperinterface(ClassName.get(interfaceType))
137 | .addModifiers(Modifier.PUBLIC)
138 | .addMethod(methodHandle.build())
139 | .addJavadoc(CLASS_JAVA_DOC)
140 | .build();
141 | try {
142 | JavaFile.builder(PACKAGE_NAME, type).build().writeTo(processingEnv.getFiler());
143 | } catch (IOException e) {
144 | e.printStackTrace();
145 | }
146 | }
147 |
148 | /**
149 | * TargetInterceptors.
150 | */
151 | private void generateTargetInterceptors(String moduleName, Set elements) {
152 | // Map, String[]> map
153 | ParameterizedTypeName mapTypeName = ParameterizedTypeName.get(
154 | ClassName.get(Map.class),
155 | ParameterizedTypeName.get(ClassName.get(Class.class),
156 | WildcardTypeName.subtypeOf(Object.class)),
157 | TypeName.get(String[].class));
158 | ParameterSpec mapParameterSpec = ParameterSpec.builder(mapTypeName, "map").build();
159 | MethodSpec.Builder methodHandle = MethodSpec.methodBuilder(HANDLE)
160 | .addAnnotation(Override.class)
161 | .addModifiers(Modifier.PUBLIC)
162 | .addParameter(mapParameterSpec);
163 | boolean hasInterceptor = false; // flag
164 | for (TypeElement element : elements) {
165 | Route route = element.getAnnotation(Route.class);
166 | String[] interceptors = route.interceptors();
167 | if (interceptors.length > 1) {
168 | hasInterceptor = true;
169 | StringBuilder sb = new StringBuilder();
170 | for (String interceptor : interceptors) {
171 | sb.append("\"").append(interceptor).append("\",");
172 | }
173 | methodHandle.addStatement("map.put($T.class, new String[]{$L})",
174 | ClassName.get(element), sb.substring(0, sb.lastIndexOf(",")));
175 | } else if (interceptors.length == 1) {
176 | hasInterceptor = true;
177 | methodHandle.addStatement("map.put($T.class, new String[]{$S})",
178 | ClassName.get(element), interceptors[0]);
179 | }
180 | }
181 | if (!hasInterceptor) { // if there are no interceptors, ignore.
182 | return;
183 | }
184 | TypeSpec type = TypeSpec.classBuilder(capitalize(moduleName) + TABLE_INTERCEPTORS)
185 | .addSuperinterface(ClassName.get(PACKAGE_NAME, TABLE_INTERCEPTORS))
186 | .addModifiers(Modifier.PUBLIC)
187 | .addMethod(methodHandle.build())
188 | .addJavadoc(CLASS_JAVA_DOC)
189 | .build();
190 | try {
191 | JavaFile.builder(PACKAGE_NAME, type).build().writeTo(processingEnv.getFiler());
192 | } catch (IOException e) {
193 | e.printStackTrace();
194 | }
195 | }
196 |
197 | private String capitalize(CharSequence self) {
198 | return self.length() == 0 ? "" :
199 | "" + Character.toUpperCase(self.charAt(0)) + self.subSequence(1, self.length());
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/compiler/src/main/java/com/smart/router/compiler/processor/InjectParamProcessor.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.compiler.processor;
2 |
3 |
4 | import com.smart.router.annotation.InjectParam;
5 | import com.smart.router.compiler.util.Logger;
6 | import com.squareup.javapoet.ClassName;
7 | import com.squareup.javapoet.JavaFile;
8 | import com.squareup.javapoet.MethodSpec;
9 | import com.squareup.javapoet.ParameterSpec;
10 | import com.squareup.javapoet.TypeName;
11 | import com.squareup.javapoet.TypeSpec;
12 |
13 | import java.io.IOException;
14 | import java.lang.reflect.Field;
15 | import java.util.ArrayList;
16 | import java.util.HashMap;
17 | import java.util.List;
18 | import java.util.Map;
19 | import java.util.Set;
20 |
21 | import javax.annotation.processing.AbstractProcessor;
22 | import javax.annotation.processing.ProcessingEnvironment;
23 | import javax.annotation.processing.RoundEnvironment;
24 | import javax.annotation.processing.SupportedAnnotationTypes;
25 | import javax.annotation.processing.SupportedOptions;
26 | import javax.annotation.processing.SupportedSourceVersion;
27 | import javax.lang.model.SourceVersion;
28 | import javax.lang.model.element.Element;
29 | import javax.lang.model.element.Modifier;
30 | import javax.lang.model.element.TypeElement;
31 | import javax.lang.model.type.ArrayType;
32 | import javax.lang.model.type.DeclaredType;
33 | import javax.lang.model.type.PrimitiveType;
34 | import javax.lang.model.type.TypeMirror;
35 |
36 | import static com.smart.router.compiler.util.Consts.ACTIVITY_FULL_NAME;
37 | import static com.smart.router.compiler.util.Consts.CLASS_JAVA_DOC;
38 | import static com.smart.router.compiler.util.Consts.FRAGMENT_FULL_NAME;
39 | import static com.smart.router.compiler.util.Consts.FRAGMENT_V4_FULL_NAME;
40 | import static com.smart.router.compiler.util.Consts.INNER_CLASS_NAME;
41 | import static com.smart.router.compiler.util.Consts.METHOD_INJECT;
42 | import static com.smart.router.compiler.util.Consts.OPTION_MODULE_NAME;
43 | import static com.smart.router.compiler.util.Consts.PACKAGE_NAME;
44 | import static com.smart.router.compiler.util.Consts.PARAM_ANNOTATION_TYPE;
45 |
46 | /**
47 | * Created by Harry.Kong.
48 | * Time 2017/11/8.
49 | * Description:annotation processor.
50 | */
51 | @SupportedAnnotationTypes(PARAM_ANNOTATION_TYPE)
52 | @SupportedOptions(OPTION_MODULE_NAME)
53 | @SupportedSourceVersion(SourceVersion.RELEASE_7)
54 | public class InjectParamProcessor extends AbstractProcessor {
55 | private String mModuleName;
56 | private Logger mLogger;
57 | private Map> mClzAndParams = new HashMap<>();
58 |
59 | @Override
60 | public synchronized void init(ProcessingEnvironment processingEnvironment) {
61 | super.init(processingEnvironment);
62 | mModuleName = processingEnvironment.getOptions().get(OPTION_MODULE_NAME);
63 | mLogger = new Logger(processingEnvironment.getMessager());
64 | }
65 |
66 | @Override
67 | public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
68 | Set extends Element> elements = roundEnvironment.getElementsAnnotatedWith(InjectParam.class);
69 | if (elements == null || elements.isEmpty()) {
70 | return true;
71 | }
72 | mLogger.info(String.format(">>> %s: InjectParamProcessor begin... <<<", mModuleName));
73 | parseParams(elements);
74 | try {
75 | generate();
76 | } catch (IllegalAccessException e) {
77 | e.printStackTrace();
78 | } catch (IOException e) {
79 | mLogger.error("Exception occurred when generating class file.");
80 | e.printStackTrace();
81 | }
82 | mLogger.info(String.format(">>> %s: InjectParamProcessor end. <<<", mModuleName));
83 | return true;
84 | }
85 |
86 | private void parseParams(Set extends Element> elements) {
87 | for (Element element : elements) {
88 | TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
89 |
90 | if (mClzAndParams.containsKey(enclosingElement)) {
91 | mClzAndParams.get(enclosingElement).add(element);
92 | } else {
93 | List params = new ArrayList<>();
94 | params.add(element);
95 | mClzAndParams.put(enclosingElement, params);
96 | }
97 | }
98 | }
99 |
100 | private void generate() throws IllegalAccessException, IOException {
101 | final String TARGET = "target";
102 | final String EXTRAS = "extras";
103 | final String OBJ = "obj";
104 |
105 | ParameterSpec objectParamSpec = ParameterSpec.builder(TypeName.OBJECT, OBJ).build();
106 |
107 | for (Map.Entry> entry : mClzAndParams.entrySet()) {
108 | TypeElement parent = entry.getKey();
109 | List params = entry.getValue();
110 |
111 | String qualifiedName = parent.getQualifiedName().toString();
112 | String simpleName = parent.getSimpleName().toString();
113 | String packageName = qualifiedName.substring(0, qualifiedName.lastIndexOf("."));
114 | String fileName = simpleName + INNER_CLASS_NAME;
115 |
116 | // validate
117 | boolean isActivity;
118 | if (isSubtype(parent, ACTIVITY_FULL_NAME)) {
119 | isActivity = true;
120 | } else if (isSubtype(parent, FRAGMENT_V4_FULL_NAME) || isSubtype(parent, FRAGMENT_FULL_NAME)) {
121 | isActivity = false;
122 | } else {
123 | throw new IllegalAccessException(
124 | String.format("The target class %s must be Activity or Fragment.", simpleName));
125 | }
126 |
127 | mLogger.info(String.format("Start to process injected params in %s ...", simpleName));
128 |
129 | // @Override
130 | // public void inject(Object obj) {}
131 | MethodSpec.Builder injectMethodBuilder = MethodSpec.methodBuilder(METHOD_INJECT)
132 | .addAnnotation(Override.class)
133 | .addModifiers(Modifier.PUBLIC)
134 | .addParameter(objectParamSpec);
135 |
136 | // XXXActivity target = (XXXActivity) obj;
137 | injectMethodBuilder.addStatement("$T $L = ($T) $L",
138 | ClassName.get(parent), TARGET, ClassName.get(parent), OBJ);
139 | if (isActivity) { // Bundle extras = target.getIntent().getExtras();
140 | injectMethodBuilder.addStatement("$T $L = $L.getIntent().getExtras()",
141 | ClassName.get("android.os", "Bundle"), EXTRAS, TARGET);
142 | } else { // Bundle extras = target.getArguments();
143 | injectMethodBuilder.addStatement("$T $L = $L.getArguments()",
144 | ClassName.get("android.os", "Bundle"), EXTRAS, TARGET);
145 | }
146 |
147 | for (Element param : params) {
148 | InjectParam injectParam = param.getAnnotation(InjectParam.class);
149 | String fieldName = param.getSimpleName().toString();
150 | String key = isEmpty(injectParam.key()) ? fieldName : injectParam.key();
151 |
152 | StringBuilder statement = new StringBuilder();
153 | if (param.getModifiers().contains(Modifier.PRIVATE)) {
154 | mLogger.warn(param, String.format(
155 | "Found private field: %s, please remove 'private' modifier for a better performance.", fieldName));
156 |
157 | String reflectName = "field_" + fieldName;
158 |
159 | injectMethodBuilder.beginControlFlow("try")
160 | .addStatement("$T $L = $T.class.getDeclaredField($S)",
161 | ClassName.get(Field.class), reflectName, ClassName.get(parent), fieldName)
162 | .addStatement("$L.setAccessible(true)", reflectName);
163 |
164 | Object[] args;
165 | // field_xxx.set(target, extras.getXXX("key"
166 | statement.append("$L.set($L, $L.get")
167 | .append(getAccessorType(param.asType()))
168 | .append("(")
169 | .append("$S");
170 | // , (FieldType) field_xxx.get(target)
171 | if (supportDefaultValue(param.asType())) {
172 | statement.append(", ($T) $L.get($L)");
173 | args = new Object[]{reflectName, TARGET, EXTRAS, key,
174 | ClassName.get(param.asType()), reflectName, TARGET};
175 | } else {
176 | args = new Object[]{reflectName, TARGET, EXTRAS, key};
177 | }
178 | // ))
179 | statement.append("))");
180 |
181 | injectMethodBuilder.addStatement(statement.toString(), args)
182 | .nextControlFlow("catch ($T e)", Exception.class)
183 | .addStatement("e.printStackTrace()")
184 | .endControlFlow();
185 | } else {
186 | Object[] args;
187 | // target.field = (FieldType) extras.getXXX("key"
188 |
189 | statement.append("$L.$L = ($T) $L.get")
190 | .append(getAccessorType(param.asType())).append("(")
191 | .append("$S");
192 | // , target.field
193 | if (supportDefaultValue(param.asType())) {
194 | statement.append(", $L.$L");
195 | args = new Object[]{TARGET, fieldName, ClassName.get(param.asType()), EXTRAS, key, TARGET, fieldName};
196 | } else {
197 | args = new Object[]{TARGET, fieldName, ClassName.get(param.asType()), EXTRAS, key};
198 | }
199 | statement.append(")");
200 |
201 | injectMethodBuilder.addStatement(statement.toString(), args);
202 | }
203 | }
204 |
205 | TypeSpec typeSpec = TypeSpec.classBuilder(fileName)
206 | .addJavadoc(CLASS_JAVA_DOC)
207 | .addSuperinterface(ClassName.get(PACKAGE_NAME, "ParamInjector"))
208 | .addModifiers(Modifier.PUBLIC)
209 | .addMethod(injectMethodBuilder.build())
210 | .build();
211 |
212 | JavaFile.builder(packageName, typeSpec).build().writeTo(processingEnv.getFiler());
213 |
214 | mLogger.info(String.format("Params in class %s have been processed: %s.", simpleName, fileName));
215 | }
216 | }
217 |
218 | private boolean supportDefaultValue(TypeMirror typeMirror) {
219 | if (typeMirror instanceof PrimitiveType) {
220 | return true;
221 | }
222 | if (isSubtype(typeMirror, "java.lang.String") || isSubtype(typeMirror, "java.lang.CharSequence")) {
223 | return true;
224 | }
225 | return false;
226 | }
227 |
228 | /**
229 | * Computes the string to append to 'get' or 'set' to get a valid Bundle method name.
230 | * For example, for the type int[], will return 'IntArray', which leads to the methods 'putIntArray' and 'getIntArray'
231 | *
232 | * @param typeMirror The type to access in the bundle
233 | * @return The string to append to 'get' or 'put'
234 | */
235 | private String getAccessorType(TypeMirror typeMirror) {
236 | if (typeMirror instanceof PrimitiveType) {
237 | return typeMirror.toString().toUpperCase().charAt(0) + typeMirror.toString().substring(1);
238 | } else if (typeMirror instanceof DeclaredType) {
239 | Element element = ((DeclaredType) typeMirror).asElement();
240 | if (element instanceof TypeElement) {
241 | if (isSubtype(element, "java.util.List")) { // ArrayList
242 | List extends TypeMirror> typeArgs = ((DeclaredType) typeMirror).getTypeArguments();
243 | if (typeArgs != null && !typeArgs.isEmpty()) {
244 | TypeMirror argType = typeArgs.get(0);
245 | if (isSubtype(argType, "java.lang.Integer")) {
246 | return "IntegerArrayList";
247 | } else if (isSubtype(argType, "java.lang.String")) {
248 | return "StringArrayList";
249 | } else if (isSubtype(argType, "java.lang.CharSequence")) {
250 | return "CharSequenceArrayList";
251 | } else if (isSubtype(argType, "android.os.Parcelable")) {
252 | return "ParcelableArrayList";
253 | }
254 | }
255 | } else if (isSubtype(element, "android.os.Bundle")) {
256 | return "Bundle";
257 | } else if (isSubtype(element, "java.lang.String")) {
258 | return "String";
259 | } else if (isSubtype(element, "java.lang.CharSequence")) {
260 | return "CharSequence";
261 | } else if (isSubtype(element, "android.util.SparseArray")) {
262 | return "SparseParcelableArray";
263 | } else if (isSubtype(element, "android.os.Parcelable")) {
264 | return "Parcelable";
265 | } else if (isSubtype(element, "java.io.Serializable")) {
266 | return "Serializable";
267 | } else if (isSubtype(element, "android.os.IBinder")) {
268 | return "Binder";
269 | }
270 | }
271 | } else if (typeMirror instanceof ArrayType) {
272 | ArrayType arrayType = (ArrayType) typeMirror;
273 | TypeMirror compType = arrayType.getComponentType();
274 | if (compType instanceof PrimitiveType) {
275 | return compType.toString().toUpperCase().charAt(0) + compType.toString().substring(1) + "Array";
276 | } else if (compType instanceof DeclaredType) {
277 | Element compElement = ((DeclaredType) compType).asElement();
278 | if (compElement instanceof TypeElement) {
279 | if (isSubtype(compElement, "java.lang.String")) {
280 | return "StringArray";
281 | } else if (isSubtype(compElement, "java.lang.CharSequence")) {
282 | return "CharSequenceArray";
283 | } else if (isSubtype(compElement, "android.os.Parcelable")) {
284 | return "ParcelableArray";
285 | }
286 | return null;
287 | }
288 | }
289 | }
290 | return null;
291 | }
292 |
293 | private boolean isSubtype(Element typeElement, String type) {
294 | return processingEnv.getTypeUtils().isSubtype(typeElement.asType(),
295 | processingEnv.getElementUtils().getTypeElement(type).asType());
296 | }
297 |
298 | private boolean isSubtype(TypeMirror typeMirror, String type) {
299 | return processingEnv.getTypeUtils().isSubtype(typeMirror,
300 | processingEnv.getElementUtils().getTypeElement(type).asType());
301 | }
302 |
303 | private boolean isEmpty(CharSequence c) {
304 | return c == null || c.length() == 0;
305 | }
306 |
307 | }
308 |
--------------------------------------------------------------------------------
/router/src/main/java/com/smart/router/router/RealRouter.java:
--------------------------------------------------------------------------------
1 | package com.smart.router.router;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Build;
7 | import android.os.Bundle;
8 | import android.support.annotation.Nullable;
9 | import android.support.v4.app.ActivityCompat;
10 | import android.support.v4.app.Fragment;
11 | import android.support.v4.app.FragmentActivity;
12 | import android.support.v4.content.ContextCompat;
13 |
14 |
15 | import com.smart.router.router.matcher.AbsImplicitMatcher;
16 | import com.smart.router.router.matcher.AbsMatcher;
17 | import com.smart.router.router.util.RLog;
18 |
19 | import java.lang.reflect.Constructor;
20 | import java.util.Collections;
21 | import java.util.HashMap;
22 | import java.util.HashSet;
23 | import java.util.List;
24 | import java.util.Map;
25 | import java.util.Set;
26 |
27 | /**
28 | *
29 | * Created by Harry.Kong.
30 | */
31 | class RealRouter extends AbsRouter {
32 | private static RealRouter sInstance;
33 | private static final String PARAM_CLASS_SUFFIX = "$$SmartRouter$$ParamInjector";
34 |
35 | private Map mInterceptorInstance = new HashMap<>();
36 |
37 | private RealRouter() {
38 | }
39 |
40 | static synchronized RealRouter getInstance() {
41 | if (sInstance == null) {
42 | sInstance = new RealRouter();
43 | }
44 | return sInstance;
45 | }
46 |
47 | /**
48 | * Handle route table.
49 | *
50 | * @param routeTable route table
51 | */
52 | void handleRouteTable(RouteTable routeTable) {
53 | if (routeTable != null) {
54 | routeTable.handle(AptHub.routeTable);
55 | }
56 | }
57 |
58 | /**
59 | * Handle interceptor table.
60 | *
61 | * @param interceptorTable interceptor table
62 | */
63 | void handleInterceptorTable(InterceptorTable interceptorTable) {
64 | if (interceptorTable != null) {
65 | interceptorTable.handle(AptHub.interceptorTable);
66 | }
67 | }
68 |
69 | /**
70 | * Handle targets' interceptors.
71 | *
72 | * @param targetInterceptors target -> interceptors
73 | */
74 | void handleTargetInterceptors(TargetInterceptors targetInterceptors) {
75 | if (targetInterceptors != null) {
76 | targetInterceptors.handle(AptHub.targetInterceptors);
77 | }
78 | }
79 |
80 | /**
81 | * Auto inject params from bundle.
82 | *
83 | * @param obj Activity or Fragment.
84 | */
85 | void injectParams(Object obj) {
86 | if (obj instanceof Activity || obj instanceof Fragment || obj instanceof android.app.Fragment) {
87 | String key = obj.getClass().getCanonicalName();
88 | Class clz;
89 | if (!AptHub.injectors.containsKey(key)) {
90 | try {
91 | //noinspection unchecked
92 | clz = (Class) Class.forName(key + PARAM_CLASS_SUFFIX);
93 | AptHub.injectors.put(key, clz);
94 | } catch (ClassNotFoundException e) {
95 | RLog.e("Inject params failed.", e);
96 | return;
97 | }
98 | } else {
99 | clz = AptHub.injectors.get(key);
100 | }
101 | try {
102 | ParamInjector injector = clz.newInstance();
103 | injector.inject(obj);
104 | } catch (Exception e) {
105 | RLog.e("Inject params failed.", e);
106 | }
107 | } else {
108 | RLog.e("The obj you passed must be an instance of Activity or Fragment.");
109 | }
110 | }
111 |
112 | private void callback(RouteResult result, String msg) {
113 | if (result != RouteResult.SUCCEED) {
114 | RLog.w(msg);
115 | }
116 | if (mRouteRequest.getCallback() != null) {
117 | mRouteRequest.getCallback().callback(result, mRouteRequest.getUri(), msg);
118 | }
119 | }
120 |
121 | @Override
122 | public Object getFragment(Context context) {
123 | if (mRouteRequest.getUri() == null) {
124 | callback(RouteResult.FAILED, "uri == null.");
125 | return null;
126 | }
127 |
128 | if (!mRouteRequest.isSkipInterceptors()) {
129 | for (RouteInterceptor interceptor : SmartRouter.getGlobalInterceptors()) {
130 | if (interceptor.intercept(context, mRouteRequest)) {
131 | callback(RouteResult.INTERCEPTED, "Intercepted by global interceptor.");
132 | return null;
133 | }
134 | }
135 | }
136 |
137 | List matcherList = MatcherRegistry.getMatcher();
138 | if (matcherList.isEmpty()) {
139 | callback(RouteResult.FAILED, "The MatcherRegistry contains no Matcher.");
140 | return null;
141 | }
142 |
143 | // fragment only matches explicit route
144 | if (AptHub.routeTable.isEmpty()) {
145 | callback(RouteResult.FAILED, "The route table contains no mapping.");
146 | return null;
147 | }
148 |
149 | Set>> entries = AptHub.routeTable.entrySet();
150 |
151 | for (AbsMatcher matcher : matcherList) {
152 | if (matcher instanceof AbsImplicitMatcher) { // Ignore implicit matcher.
153 | continue;
154 | }
155 | for (Map.Entry> entry : entries) {
156 | if (matcher.match(context, mRouteRequest.getUri(), entry.getKey(), mRouteRequest)) {
157 | RLog.i("Caught by " + matcher.getClass().getCanonicalName());
158 | if (intercept(context, entry.getValue())) {
159 | return null;
160 | }
161 | Object result = matcher.generate(context, mRouteRequest.getUri(), entry.getValue());
162 | if (result instanceof Fragment) {
163 | Fragment fragment = (Fragment) result;
164 | Bundle bundle = mRouteRequest.getExtras();
165 | if (bundle != null && !bundle.isEmpty()) {
166 | fragment.setArguments(bundle);
167 | }
168 | return fragment;
169 | } else if (result instanceof android.app.Fragment) {
170 | android.app.Fragment fragment = (android.app.Fragment) result;
171 | Bundle bundle = mRouteRequest.getExtras();
172 | if (bundle != null && !bundle.isEmpty()) {
173 | fragment.setArguments(bundle);
174 | }
175 | return fragment;
176 | } else {
177 | callback(RouteResult.FAILED, String.format(
178 | "The matcher can't generate a fragment instance for uri: %s",
179 | mRouteRequest.getUri().toString()));
180 | return null;
181 | }
182 | }
183 | }
184 | }
185 |
186 | callback(RouteResult.FAILED, String.format(
187 | "Can not find an Fragment that matches the given uri: %s", mRouteRequest.getUri()));
188 | return null;
189 | }
190 |
191 | @Override
192 | public Intent getIntent(Context context) {
193 | if (mRouteRequest.getUri() == null) {
194 | callback(RouteResult.FAILED, "uri == null.");
195 | return null;
196 | }
197 |
198 | if (!mRouteRequest.isSkipInterceptors()) {
199 | for (RouteInterceptor interceptor : SmartRouter.getGlobalInterceptors()) {
200 | if (interceptor.intercept(context, mRouteRequest)) {
201 | callback(RouteResult.INTERCEPTED, "Intercepted by global interceptor.");
202 | return null;
203 | }
204 | }
205 | }
206 |
207 | List matcherList = MatcherRegistry.getMatcher();
208 | if (matcherList.isEmpty()) {
209 | callback(RouteResult.FAILED, "The MatcherRegistry contains no Matcher.");
210 | return null;
211 | }
212 |
213 | Set>> entries = AptHub.routeTable.entrySet();
214 |
215 | for (AbsMatcher matcher : matcherList) {
216 | if (AptHub.routeTable.isEmpty()) { // implicit totally.
217 | if (matcher.match(context, mRouteRequest.getUri(), null, mRouteRequest)) {
218 | RLog.i("Caught by " + matcher.getClass().getCanonicalName());
219 | return finalizeIntent(context, matcher, null);
220 | }
221 | } else {
222 | for (Map.Entry> entry : entries) {
223 | if (matcher.match(context, mRouteRequest.getUri(), entry.getKey(), mRouteRequest)) {
224 | RLog.i("Caught by " + matcher.getClass().getCanonicalName());
225 | return finalizeIntent(context, matcher, entry.getValue());
226 | }
227 | }
228 | }
229 | }
230 |
231 | callback(RouteResult.FAILED, String.format(
232 | "Can not find an Activity that matches the given uri: %s", mRouteRequest.getUri()));
233 | return null;
234 | }
235 |
236 | /**
237 | * Do intercept and then generate intent by the given matcher, finally assemble extras.
238 | *
239 | * @param context Context
240 | * @param matcher current matcher
241 | * @param target route target
242 | * @return Finally intent.
243 | */
244 | private Intent finalizeIntent(Context context, AbsMatcher matcher, @Nullable Class> target) {
245 | if (intercept(context, target)) {
246 | return null;
247 | }
248 | Object intent = matcher.generate(context, mRouteRequest.getUri(), target);
249 | if (intent instanceof Intent) {
250 | assembleIntent((Intent) intent);
251 | return (Intent) intent;
252 | } else {
253 | callback(RouteResult.FAILED, String.format(
254 | "The matcher can't generate an intent for uri: %s",
255 | mRouteRequest.getUri().toString()));
256 | return null;
257 | }
258 | }
259 |
260 | private void assembleIntent(Intent intent) {
261 | if (intent == null) {
262 | return;
263 | }
264 | if (mRouteRequest.getExtras() != null && !mRouteRequest.getExtras().isEmpty()) {
265 | intent.putExtras(mRouteRequest.getExtras());
266 | }
267 | if (mRouteRequest.getFlags() != 0) {
268 | intent.addFlags(mRouteRequest.getFlags());
269 | }
270 | if (mRouteRequest.getData() != null) {
271 | intent.setData(mRouteRequest.getData());
272 | }
273 | if (mRouteRequest.getType() != null) {
274 | intent.setType(mRouteRequest.getType());
275 | }
276 | if (mRouteRequest.getAction() != null) {
277 | intent.setAction(mRouteRequest.getAction());
278 | }
279 | }
280 |
281 | /**
282 | * Find interceptors
283 | *
284 | * @param context Context
285 | * @param target target page.
286 | * @return True if intercepted, false otherwise.
287 | */
288 | private boolean intercept(Context context, @Nullable Class> target) {
289 | if (mRouteRequest.isSkipInterceptors()) {
290 | return false;
291 | }
292 | // Assemble final interceptors
293 | Set finalInterceptors = new HashSet<>();
294 | if (target != null) {
295 | // 1. Add original interceptors in Map
296 | String[] baseInterceptors = AptHub.targetInterceptors.get(target);
297 | if (baseInterceptors != null && baseInterceptors.length > 0) {
298 | Collections.addAll(finalInterceptors, baseInterceptors);
299 | }
300 | // 2. Skip temp removed interceptors
301 | if (mRouteRequest.getRemovedInterceptors() != null) {
302 | finalInterceptors.removeAll(mRouteRequest.getRemovedInterceptors());
303 | }
304 | }
305 | // 3. Add temp added interceptors
306 | if (mRouteRequest.getAddedInterceptors() != null) {
307 | finalInterceptors.addAll(mRouteRequest.getAddedInterceptors());
308 | }
309 |
310 | if (!finalInterceptors.isEmpty()) {
311 | for (String name : finalInterceptors) {
312 | RouteInterceptor interceptor = mInterceptorInstance.get(name);
313 | if (interceptor == null) {
314 | Class extends RouteInterceptor> clz = AptHub.interceptorTable.get(name);
315 | try {
316 | Constructor extends RouteInterceptor> constructor = clz.getConstructor();
317 | interceptor = constructor.newInstance();
318 | mInterceptorInstance.put(name, interceptor);
319 | } catch (Exception e) {
320 | RLog.e("Can't construct a interceptor with name: " + name);
321 | e.printStackTrace();
322 | }
323 | }
324 | // do intercept
325 | if (interceptor != null && interceptor.intercept(context, mRouteRequest)) {
326 | callback(RouteResult.INTERCEPTED, String.format(
327 | "Intercepted: {uri: %s, interceptor: %s}",
328 | mRouteRequest.getUri().toString(), name));
329 | return true;
330 | }
331 | }
332 | }
333 | return false;
334 | }
335 |
336 | @Override
337 | public void go(Context context) {
338 | Intent intent = getIntent(context);
339 | if (intent == null) {
340 | return;
341 | }
342 |
343 | Bundle options = mRouteRequest.getActivityOptionsCompat() == null ?
344 | null : mRouteRequest.getActivityOptionsCompat().toBundle();
345 |
346 | if (context instanceof Activity) {
347 | ActivityCompat.startActivityForResult((Activity) context, intent,
348 | mRouteRequest.getRequestCode(), options);
349 |
350 | if (mRouteRequest.getEnterAnim() != 0 && mRouteRequest.getExitAnim() != 0) {
351 | // Add transition animation.
352 | ((Activity) context).overridePendingTransition(
353 | mRouteRequest.getEnterAnim(), mRouteRequest.getExitAnim());
354 | }
355 | } else {
356 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
357 | ContextCompat.startActivity(context, intent, options);
358 | }
359 |
360 | callback(RouteResult.SUCCEED, null);
361 | }
362 |
363 |
364 | @Override
365 | public void go(Fragment fragment) {
366 | FragmentActivity activity = fragment.getActivity();
367 | Context context = fragment.getContext();
368 | Intent intent = getIntent(activity != null ? activity : context);
369 | if (intent == null) {
370 | return;
371 | }
372 | Bundle options = mRouteRequest.getActivityOptionsCompat() == null ?
373 | null : mRouteRequest.getActivityOptionsCompat().toBundle();
374 |
375 | if (mRouteRequest.getRequestCode() < 0) {
376 | fragment.startActivity(intent, options);
377 | } else {
378 | fragment.startActivityForResult(intent, mRouteRequest.getRequestCode(), options);
379 | }
380 | if (activity != null && mRouteRequest.getEnterAnim() != 0 && mRouteRequest.getExitAnim() != 0) {
381 | // Add transition animation.
382 | activity.overridePendingTransition(
383 | mRouteRequest.getEnterAnim(), mRouteRequest.getExitAnim());
384 | }
385 |
386 | callback(RouteResult.SUCCEED, null);
387 | }
388 |
389 |
390 | @Override
391 | public void go(android.app.Fragment fragment) {
392 | Activity activity = fragment.getActivity();
393 | Intent intent = getIntent(activity);
394 | if (intent == null) {
395 | return;
396 | }
397 | Bundle options = mRouteRequest.getActivityOptionsCompat() == null ?
398 | null : mRouteRequest.getActivityOptionsCompat().toBundle();
399 |
400 | if (mRouteRequest.getRequestCode() < 0) {
401 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // 4.1
402 | fragment.startActivity(intent, options);
403 | } else {
404 | fragment.startActivity(intent);
405 | }
406 | } else {
407 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { // 4.1
408 | fragment.startActivityForResult(intent, mRouteRequest.getRequestCode(), options);
409 | } else {
410 | fragment.startActivityForResult(intent, mRouteRequest.getRequestCode());
411 | }
412 | }
413 | if (activity != null && mRouteRequest.getEnterAnim() != 0 && mRouteRequest.getExitAnim() != 0) {
414 | // Add transition animation.
415 | activity.overridePendingTransition(
416 | mRouteRequest.getEnterAnim(), mRouteRequest.getExitAnim());
417 | }
418 |
419 | callback(RouteResult.SUCCEED, null);
420 | }
421 | }
422 |
--------------------------------------------------------------------------------