WMRouter 启动 Activity 源码解析
本文最后更新于 1041 天前,其中的信息可能已经有所发展或是发生改变。

0x00 写在前面

WMRouter 是美团外卖团队开发的一款 Android 路由框架,和阿里开发的 ARouter 比较类似。不过因为项目的原因,我接触 WMRouter 要更多一点。

有关 WMRouter 的 API 的介绍,可以参考 WMRouter 的 GitHub 页面,这里就不多介绍了:https://github.com/meituan/WMRouter/blob/master/docs/user-manual.md

0x01 Handler 是如何处理请求的

标题里所说的 Handler,其实不是 Android 系统中的那个 Handler,而是 WMRouter 中的 UriHandler。它的用途就是来处理请求。这个请求的来源可能是多种多样的,比如应用内发起的跳转请求,或者是其他应用甚至是网页发起的请求。

对于这些各种来源的请求,必然要有地方处理这些请求,将这些请求分发给 Activity。WMRouter 中就是由各种 UriHandler 来处理请求的。

WMRouter 对这一设计的描述如下图所示:

WMRouter 的 UriHandler 处理

其中,UriRequest 代表一个请求,这个请求并不是直接就能用来启动 Activity 的,而是通过一个个的 UriHandler 来处理的。

接下来,我们就从最基本的启动 Activity 代码说起。

Router.startUri

Router 类提供了一个 startUri() 方法,用来快速启动一个 Activity。

Router.startUri(MainActivity.this, "/second_activity");

这个 startUri() 方法传入一个 Context,传入一个 String。这个 String 字符串就是 Activity 对应的路径。startUri() 方法的源码如下:

public class Router {
    // ...

    public static void startUri(Context context, String uri) {
        getRootHandler().startUri(new UriRequest(context, uri));
    }
}

可以看到,实际上它是去获取了 RootUriHandler,然后执行它的 startUri() 方法。而 RootUriHandlerstartUri() 方法传入的是一个 UriRequest

RootUriHandler.startUri

RootUriHandler 会对传入的 UriRequest 进行检查,例如看看传入的 UriRequest 是否为 nullContext 或者跳转链接是否为空。

public class RootUriHandler extends ChainedHandler {
    // ...
  
    public void startUri(@NonNull UriRequest request) {
        if (request == null) {
            String msg = "UriRequest为空";
            Debugger.fatal(msg);
            UriRequest req = new UriRequest(mContext, Uri.EMPTY).setErrorMessage(msg);
            onError(req, UriResult.CODE_BAD_REQUEST);
        } else if (request.getContext() == null) {
            String msg = "UriRequest.Context为空";
            Debugger.fatal(msg);
            UriRequest req = new UriRequest(mContext, request.getUri(), request.getFields())
                    .setErrorMessage(msg);
            onError(req, UriResult.CODE_BAD_REQUEST);
        } else if (request.isUriEmpty()) {
            String msg = "跳转链接为空";
            Debugger.e(msg);
            request.setErrorMessage(msg);
            onError(request, UriResult.CODE_BAD_REQUEST);
        } else {
            // 这个请求是正常的
            if (Debugger.isEnableLog()) {
                Debugger.i("");
                Debugger.i("---> receive request: %s", request.toFullString());
            }
            // 真正处理请求的方法:
            handle(request, new RootUriCallback(request));
        }
    }
}

可以看到上面这段代码我给出的注释里,提到真正处理请求的方法其实就是 handle() 方法。这个方法是定义在 UriHandler 类里的,用于判断当前 Handler 是否应该处理这个请求,以及执行拦截器相关的逻辑。

UriHandler.handle

UriHandler 是所有 Handler 的基类,它主要是定义了 addInterceptor() 方法和 handle() 方法。其中,addInterceptor() 方法是和拦截器有关的,不在这篇文章的讨论范围内,所以暂时略过。我们现在只看和处理请求有关的 handle() 方法:

public abstract class UriHandler {
    // ...
  
    public void handle(@NonNull final UriRequest request, @NonNull final UriCallback callback) {
        // 是否应该由当前 Handler 来处理这个请求?
      	if (shouldHandle(request)) {
            // 应该由当前 Handler 来处理
            Debugger.i("%s: handle request %s", this, request);
            // 如果拦截器不为空,那么应该先执行所有的拦截器,最后再处理请求
            if (mInterceptor != null && !request.isSkipInterceptors()) {
              	// 这里 intercept 方法实际上是执行了所有的拦截器
                mInterceptor.intercept(request, new UriCallback() {
                    @Override
                    public void onNext() {
                      	// onNext() 表示所有拦截器处理完以后,判定要继续处理这个请求
                      	// 如果确定要处理这个请求,那么就执行 handleInternal() 方法来处理
                        handleInternal(request, callback);
                    }

                    @Override
                    public void onComplete(int result) {
                      	// onComplete() 表示有拦截器拦截了这个请求
                      	// 这样一来,这个请求就不会被处理
                        callback.onComplete(result);
                    }
                });
            } else {
              	// 没有拦截器,直接处理请求
                handleInternal(request, callback);
            }
        } else {
            // 不应该由当前 Handler 来处理这个请求,所以通过 callback.onNext() 交给下一个 Handler
            Debugger.i("%s: ignore request %s", this, request);
            callback.onNext();
        }
    }
  
    protected abstract boolean shouldHandle(@NonNull UriRequest request);
  
    protected abstract void handleInternal(@NonNull UriRequest request, @NonNull UriCallback callback);
}

在上面的代码中可以看到,handle() 方法通过 shouldHandle() 方法来判断是否需要由当前 Handler 来处理这个请求,然后由 handleInternal() 方法进行处理。这两个方法都是抽象方法,等待子类去实现。

实际上,这两个方法是定义在 ChainedHandler 类中的。ChainedHandlerUriHandler 的子类、RootUriHandler 的父类。

ChainedHandler

ChainedHandler 类主要是用来添加多个 Handler 的,并且允许这些 Handler 按照优先级进行排序处理。当一个 Handler 处理不了请求时,它就会将这个请求交给下一个 Handler 进行处理。

public class ChainedHandler extends UriHandler {
    private final PriorityList<UriHandler> mHandlers = new PriorityList<>();
  
    // 添加一个 Handler
    public ChainedHandler addChildHandler(@NonNull UriHandler handler, int priority) {
        mHandlers.addItem(handler, priority);
        return this;
    }
  
    // ...
  
    @Override
    protected boolean shouldHandle(@NonNull UriRequest request) {
      	// 只要 Handler 不为空,那就应该进行处理
      	// 因为 ChainedHandler 它是非常基础的 Handler,所以它始终应该处理请求
        return !mHandlers.isEmpty();
    }

    @Override
    protected void handleInternal(@NonNull final UriRequest request, @NonNull final UriCallback callback) {
      	// 把请求交给下一个 Handler 进行处理
        next(mHandlers.iterator(), request, callback);
    }

    private void next(@NonNull final Iterator<UriHandler> iterator, @NonNull final UriRequest request,
                      @NonNull final UriCallback callback) {
      	// 还有 Handler 吗?
        if (iterator.hasNext()) {
            // 有 Handler,就把这个请求交给这个 Handler 来处理
            UriHandler t = iterator.next();
            // 注意,这里没有使用传入的 callback。因为传入的 callback 是整个处理的 callback,
            // 实际上也就是 RootUriHandler.RootUriCallback。而这个 Callback 执行 onNext()
            // 和 onComplete() 都是终止处理请求,它是给请求处理兜底的。所以这里是创建新的
            // UriCallback
            t.handle(request, new UriCallback() {
                @Override
                public void onNext() {
                    // 如果当前取出的 Handler 处理不了这个请求,那么就递归执行 next() 方法,
                    // 继续取出下一个 Handler 来处理请求
                    next(iterator, request, callback);
                }

                @Override
                public void onComplete(int resultCode) {
                    // 当前 Handler 处理完成了,是成功还是失败不管,都交给
                    // RootUriHandler.RootUriCallback 去判断
                    callback.onComplete(resultCode);
                }
            });
        } else {
            // 已经没有 Handler 能处理请求了,这个请求就是处理不了了
            // 交给 RootUriHandler.RootUriCallback 去判断
            callback.onNext();
        }
    }
}

那么,知道了 ChainedHandler 类是怎么将一个请求逐一递交给其他的 Handler 以后,我们就应该继续去了解我们的请求到底都交给了谁去处理,它们都是怎么处理的。所以检查一下 addChildHandler() 方法在哪里被调用了:

addChildHandler() 主要是 DefaultRootUriHandler 类用到

从图中可以看出来,addChildHandler() 主要是 DefaultRootUriHandler 类用到。

DefaultRootUriHandler

DefaultRootUriHandler 类看起来比较熟悉,实际上它就是应用在初始化 WMRouter 时设置的那个 Handler:

public class App extends Application {
  	@Override
  	public void onCreate() {
      	// ...
      
      	DefaultRootUriHandler handler = new DefaultRootUriHandler(this);
      	Router.init(handler);
    }
}

它的主要用处其实就是继承 RootUriHandler,然后设置一下几种 Handler 以及它们的优先级。

public class DefaultRootUriHandler extends RootUriHandler {

    private final PageAnnotationHandler mPageAnnotationHandler;
    private final UriAnnotationHandler mUriAnnotationHandler;
    private final RegexAnnotationHandler mRegexAnnotationHandler;

    public DefaultRootUriHandler(Context context) {
        this(context, null, null);
    }

    public DefaultRootUriHandler(Context context,
                                 @Nullable String defaultScheme, @Nullable String defaultHost) {
        super(context);
        mPageAnnotationHandler = createPageAnnotationHandler();
        mUriAnnotationHandler = createUriAnnotationHandler(defaultScheme, defaultHost);
        mRegexAnnotationHandler = createRegexAnnotationHandler();

        // 按优先级排序,数字越大越先执行

        // 处理RouterPage注解定义的内部页面跳转,如果注解没定义,直接结束分发
        addChildHandler(mPageAnnotationHandler, 300);
        // 处理RouterUri注解定义的URI跳转,如果注解没定义,继续分发到后面的Handler
        addChildHandler(mUriAnnotationHandler, 200);
        // 处理RouterRegex注解定义的正则匹配
        addChildHandler(mRegexAnnotationHandler, 100);
        // 添加其他用户自定义Handler...

        // 都没有处理,则尝试使用默认的StartUriHandler直接启动Uri
        addChildHandler(new StartUriHandler(), -100);
        // 全局OnCompleteListener,用于输出跳转失败提示信息
        setGlobalOnCompleteListener(DefaultOnCompleteListener.INSTANCE);
    }

    // ...

    @NonNull
    protected PageAnnotationHandler createPageAnnotationHandler() {
        return new PageAnnotationHandler();
    }

    @NonNull
    protected UriAnnotationHandler createUriAnnotationHandler(@Nullable String defaultScheme,
                                                              @Nullable String defaultHost) {
        return new UriAnnotationHandler(defaultScheme, defaultHost);
    }

    @NonNull
    protected RegexAnnotationHandler createRegexAnnotationHandler() {
        return new RegexAnnotationHandler();
    }
}

因为我们的 Activity 基本上都是通过 @RouterUri 进行注释的,所以应该去看 UriAnnotationHandler 类是怎么处理请求的。

UriAnnotationHandler

UriAnnotationHandler 也并不是直接处理请求的地方,它的作用主要有两个:

  • 加载所有 Activity 的路径和 Class 名称,并注册到 PathHandler;
  • 根据 Scheme 和 Host 来查找相应的 PathHandler,然后交给 PathHandler 来处理。
public class UriAnnotationHandler extends UriHandler {
  	// key 是由 scheme + host 生成的字符串,value 是 PathHandler
  	// 也就是说,只要 scheme 和 host 相同,那么就共用一个 PathHandler
  	// 所以同一个应用基本都使用同一个 PathHandler
  	private final Map<String, PathHandler> mMap = new HashMap<>();
  
  	public void register(String scheme, String host, String path,
                         Object handler, boolean exported, UriInterceptor... interceptors) {
        // 如果没有设置 Scheme 和 Host,就用默认的值
        if (TextUtils.isEmpty(scheme)) {
            scheme = mDefaultScheme;
        }
        if (TextUtils.isEmpty(host)) {
            host = mDefaultHost;
        }
      	// 根据 Scheme 和 Host 来拼接一下
        String schemeHost = RouterUtils.schemeHost(scheme, host);
      	// 检查一下有没有已经注册了的 PathHandler,如果没有,就创建一个新的
        PathHandler pathHandler = mMap.get(schemeHost);
        if (pathHandler == null) {
            pathHandler = createPathHandler();
            mMap.put(schemeHost, pathHandler);
        }
      	// 让 PathHandler 注册一下
        pathHandler.register(path, handler, exported, interceptors);
    }

  	// ...
  
  	private PathHandler getChild(@NonNull UriRequest request) {
        return mMap.get(request.schemeHost());
    }
  
  	@Override
    protected boolean shouldHandle(@NonNull UriRequest request) {
      	// 如果 PathHandler 不为空,那么就应该把请求交给对应的 PathHandler 处理
        return getChild(request) != null;
    }

    @Override
    protected void handleInternal(@NonNull UriRequest request, @NonNull UriCallback callback) {
        PathHandler pathHandler = getChild(request);
        if (pathHandler != null) {
            // 把请求交给对应的 PathHandler 处理
            pathHandler.handle(request, callback);
        } else {
            // 没找到的继续分发
            callback.onNext();
        }
    }
}

总结一下,UriAnnotationHandler 的主要用途就是把不同 Scheme + Host 的 Activity 注册到不同的 PathHandler 类实例,然后让 PathHandler 再进一步处理。

而注册 Path 和 Activity 类名的地方是由 WMRouter 自动生成的:

public class UriAnnotationInit_3088f6f0eae502e685b028719c160ee8 implements IUriAnnotationInit {
  public void init(UriAnnotationHandler handler) {
    handler.register("", "", "/second", "me.maronyea.routertest.activity.SecondActivity", false);
  }
}

通过这样的代码,就把一个 Activity 类和 Scheme、Host、Path 给一一对应起来了。在执行 register() 方法时,实际上这些数据都交给了 PathHandler 类进行注册。

PathHandler

PathHandler 实际上也不是真正处理请求的地方,它的作用是在注册时根据 Path 来查找真正处理请求的 Handler 并将请求交给它们处理。

public class PathHandler extends UriHandler {
  	private final CaseInsensitiveNonNullMap<UriHandler> mMap = new CaseInsensitiveNonNullMap<>();
  
  	// 注册 Path 和 Activity 的对应关系
  	public void register(String path, Object target, boolean exported,
            UriInterceptor... interceptors) {
        if (!TextUtils.isEmpty(path)) {
            path = RouterUtils.appendSlash(path);
            // 根据 Path 来查找能够处理请求的 Handler
            UriHandler parse = UriTargetTools.parse(target, exported, interceptors);
            UriHandler prev = mMap.put(path, parse);
            if (prev != null) {
                Debugger.fatal("[%s] 重复注册path='%s'的UriHandler: %s, %s", this, path, prev, parse);
            }
        }
    }
  
  	// ...
  
  	// 根据请求的 Path 来找到注册时查找到的 Handler
  	private UriHandler getChild(@NonNull UriRequest request) {
        String path = request.getUri().getPath();
        if (TextUtils.isEmpty(path)) {
            return null;
        }
        path = RouterUtils.appendSlash(path);
        if (TextUtils.isEmpty(mPathPrefix)) {
            return mMap.get(path);
        }
        if (path.startsWith(mPathPrefix)) {
            return mMap.get(path.substring(mPathPrefix.length()));
        }
        return null;
    }
  
  	@Override
    protected boolean shouldHandle(@NonNull UriRequest request) {
        return mDefaultHandler != null || getChild(request) != null;
    }

    @Override
    protected void handleInternal(@NonNull final UriRequest request,
            @NonNull final UriCallback callback) {
      	// 根据请求来查找真正处理请求的 Handler,并交给它进行处理
        UriHandler h = getChild(request);
        if (h != null) {
            h.handle(request, new UriCallback() {
                @Override
                public void onNext() {
                    handleByDefault(request, callback);
                }

                @Override
                public void onComplete(int resultCode) {
                    callback.onComplete(resultCode);
                }
            });
        } else {
            handleByDefault(request, callback);
        }
    }

    private void handleByDefault(@NonNull UriRequest request, @NonNull UriCallback callback) {
        UriHandler defaultHandler = mDefaultHandler;
        if (defaultHandler != null) {
            defaultHandler.handle(request, callback);
        } else {
            callback.onNext();
        }
    }
}

注意到里面有一句关键的代码:

UriHandler parse = UriTargetTools.parse(target, exported, interceptors);

通过 UriTargetTools.parse() 方法来判断要启动这一 Activity 应该使用什么 Handler 来处理。

UriTargetTools.parse

UriTargetTools 类提供了一个 public 的方法 parse(),用来根据注册信息匹配相应的 Handler。这个方法不执行这个 Handler,只是返回 UriHandler 的实例。

public class UriTargetTools {

    public static UriHandler parse(Object target, boolean exported,
            UriInterceptor... interceptors) {
        UriHandler handler = toHandler(target);
        if (handler != null) {
            if (!exported) {
                handler.addInterceptor(NotExportedInterceptor.INSTANCE);
            }
            handler.addInterceptors(interceptors);
        }
        return handler;
    }

    private static UriHandler toHandler(Object target) {
        if (target instanceof UriHandler) {
            return (UriHandler) target;
        } else if (target instanceof String) {
            return new ActivityClassNameHandler((String) target);
        } else if (target instanceof Class && isValidActivityClass((Class) target)) {
            //noinspection unchecked
            return new ActivityHandler((Class<? extends Activity>) target);
        } else {
            return null;
        }
    }

    private static boolean isValidActivityClass(Class clazz) {
        return clazz != null && Activity.class.isAssignableFrom(clazz)
                && !Modifier.isAbstract(clazz.getModifiers());
    }
}

根据上面的代码总结一下:

  • 如果在注册时传入的 Activity 信息是以类名字符串的形式传入的,那么就交给 ActivityClassNameHandler 来处理;
  • 如果在在注册时传入的 Activity 信息是以Class 类型实例的形式传入的,那么先验证这个类是不是 Activity,如果是,那么就交给 ActivityHandler 来处理。

ActivityClassNameHandler 与 ActivityHandler

ActivityClassNameHandlerAbsActivityHandler 的子类,它其实只是提供了创建 Intent 的逻辑,真正实现处理请求的逻辑是在 AbsActivityHandler 类中实现的。

public class ActivityClassNameHandler extends AbsActivityHandler {
    // ...

    @NonNull
    @Override
    protected Intent createIntent(@NonNull UriRequest request) {
        return new Intent().setClassName(request.getContext(), mClassName);
    }
}

ActivityHandler 同样也是 AbsActivityHandler 的子类,它同样是提供了创建 Intent 的逻辑,真正实现处理请求的逻辑也是在 AbsActivityHandler 中实现的。

public class ActivityHandler extends AbsActivityHandler {
    // ...

    @NonNull
    @Override
    protected Intent createIntent(@NonNull UriRequest request) {
        return new Intent(request.getContext(), mClazz);
    }
}

AbsActivityHandler

AbsActivityHandler 类中实现了 shouldHandle()handleInternal() 方法。其中 shouldHandle() 始终返回 true,而 handleInternal() 方法则调用 createIntent() 抽象方法来创建 Intent,并通过 RouterComponents.startActivity() 方法来启动 Activity。

public abstract class AbsActivityHandler extends UriHandler {

    @Override
    protected boolean shouldHandle(@NonNull UriRequest request) {
        return true;
    }

    @SuppressWarnings("ConstantConditions")
    @Override
    protected void handleInternal(@NonNull UriRequest request, @NonNull UriCallback callback) {
        // 创建Intent
        Intent intent = createIntent(request);
        if (intent == null || intent.getComponent() == null) {
            Debugger.fatal("AbsActivityHandler.createIntent()应返回的带有ClassName的显式跳转Intent");
            callback.onComplete(UriResult.CODE_ERROR);
            return;
        }
        intent.setData(request.getUri());
        UriSourceTools.setIntentSource(intent, request);
        // 启动Activity
        request.putFieldIfAbsent(ActivityLauncher.FIELD_LIMIT_PACKAGE, limitPackage());
        int resultCode = RouterComponents.startActivity(request, intent);
        // 回调方法
        onActivityStartComplete(request, resultCode);
        // 完成
        callback.onComplete(resultCode);
    }
  
    @NonNull
    protected abstract Intent createIntent(@NonNull UriRequest request);

    /**
     * 回调方法,子类可在此实现跳转动画等效果
     *
     * @param resultCode 跳转结果
     */
    protected void onActivityStartComplete(@NonNull UriRequest request, int resultCode) { }
}

那么截至这里,就已经分析完了 Handler 的处理部分。总结一下,通过这些 UriHandler 一层层地传递请求,已经成功地还原出了用于启动 Activity 的 Intent。接下来就是要实现启动 Activity 的逻辑了。

0x02 如何启动 Activity

启动 Activity 看起来也非常的简单,既然前面已经创建了 Intent,那直接来启动不就行了吗?但实际上没有那么简单。

RouterComponents.startActivity

在上一节提到,WMRouter 通过 RouterComponents.startActivity() 方法来启动 Activity,这个方法需要传入一个 UriRequest 和 Intent。

public class RouterComponents {
    // ...

    @NonNull
    private static ActivityLauncher sActivityLauncher = DefaultActivityLauncher.INSTANCE;

    public static void setActivityLauncher(ActivityLauncher launcher) {
        sActivityLauncher = launcher == null ? DefaultActivityLauncher.INSTANCE : launcher;
    }

    // ...

    public static int startActivity(@NonNull UriRequest request, @NonNull Intent intent) {
        return sActivityLauncher.startActivity(request, intent);
    }
}

注意到 RouterComponents 类并没有直接提供启动 Activity 的逻辑,而是调用了 ActivityLauncherstartActivity() 方法去启动的。这样做同样是为了可以扩展功能,也就是说,如果将来想要自定义启动 Activity 逻辑的话,只要实现 ActivityLauncher 接口,然后通过 RouterComponents.setActivityLauncher() 方法就可以替换掉默认的启动逻辑。

不过这里暂时不展开,还是先看看默认的启动逻辑是什么样的吧。

DefaultActivityLauncher

DefaultActivityLauncher 的代码比较长,但是实际上可以看到,还是通过 ActivityCompat.startActivity() 或者 ActivityCompat.startActivityForResult() 方法去启动 Activity 的,只不过是加上了一些判断,以及从 UriRequest 中提取出来了 Bundle 和 Flag。

public class DefaultActivityLauncher implements ActivityLauncher {

    public static final DefaultActivityLauncher INSTANCE = new DefaultActivityLauncher();

    private boolean mCheckIntentFirst = false;

    /**
     * 跳转前是否先检查Intent
     */
    public void setCheckIntentFirst(boolean checkIntentFirst) {
        mCheckIntentFirst = checkIntentFirst;
    }

    @SuppressWarnings("ConstantConditions")
    public int startActivity(@NonNull UriRequest request, @NonNull Intent intent) {

        if (request == null || intent == null) {
            return UriResult.CODE_ERROR;
        }

        Context context = request.getContext();

        // Extra
        Bundle extra = request.getField(Bundle.class, FIELD_INTENT_EXTRA);
        if (extra != null) {
            intent.putExtras(extra);
        }

        // Flags
        Integer flags = request.getField(Integer.class, FIELD_START_ACTIVITY_FLAGS);
        if (flags != null) {
            intent.setFlags(flags);
        }

        // request code
        Integer requestCode = request.getField(Integer.class, FIELD_REQUEST_CODE);

        // 是否限制Intent的packageName,限制后只会启动当前App内的页面,不启动其他App的页面,bool型
        boolean limitPackage = request.getBooleanField(FIELD_LIMIT_PACKAGE, false);

        // 设置package,先尝试启动App内的页面
        intent.setPackage(context.getPackageName());

        int r = startIntent(request, intent, context, requestCode, true);

        if (limitPackage || r == UriResult.CODE_SUCCESS) {
            return r;
        }

        // App内启动失败,再尝试启动App外页面
        intent.setPackage(null);

        return startIntent(request, intent, context, requestCode, false);
    }

    /**
     * 启动Intent
     *
     * @param internal 是否启动App内页面
     */
    protected int startIntent(@NonNull UriRequest request, @NonNull Intent intent,
                              Context context, Integer requestCode, boolean internal) {
        if (!checkIntent(context, intent)) {
            return UriResult.CODE_NOT_FOUND;
        }

        if (startActivityByAction(request, intent, internal) == UriResult.CODE_SUCCESS) {
            return UriResult.CODE_SUCCESS;
        }

        return startActivityByDefault(request, context, intent, requestCode, internal);
    }

    /**
     * 检查Intent是否可跳转
     */
    protected boolean checkIntent(Context context, Intent intent) {
        if (mCheckIntentFirst) {
            try {
                PackageManager pm = context.getPackageManager();
                List list = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
                return list != null && list.size() > 0;
            } catch (Exception e) {
                // package manager has died
                Debugger.fatal(e);
                return false;
            }
        } else {
            return true;
        }
    }

    /**
     * 使用指定的 {@link StartActivityAction} 启动Intent
     *
     * @param internal 是否启动App内页面
     */
    protected int startActivityByAction(@NonNull UriRequest request,
                                        @NonNull Intent intent, boolean internal) {
        // ...
    }

    /**
     * 使用默认方式启动Intent
     *
     * @param internal 是否启动App内页面
     */
    protected int startActivityByDefault(UriRequest request, @NonNull Context context,
                                         @NonNull Intent intent, Integer requestCode, boolean internal) {
        try {
            Bundle options = request.getField(Bundle.class, FIELD_START_ACTIVITY_OPTIONS);

            if (requestCode != null && context instanceof Activity) {
                ActivityCompat.startActivityForResult((Activity) context, intent, requestCode,
                        options);
            } else {
                ActivityCompat.startActivity(context, intent, options);
            }
            doAnimation(request);

            if (internal) {
                request.putField(FIELD_STARTED_ACTIVITY, INTERNAL_ACTIVITY);
                Debugger.i("    internal activity started"
                        + ", request = %s", request);
            } else {
                request.putField(FIELD_STARTED_ACTIVITY, EXTERNAL_ACTIVITY);
                Debugger.i("    external activity started"
                        + ", request = %s", request);
            }

            return UriResult.CODE_SUCCESS;
        } catch (ActivityNotFoundException e) {
            Debugger.w(e);
            return UriResult.CODE_NOT_FOUND;
        } catch (SecurityException e) {
            Debugger.w(e);
            return UriResult.CODE_FORBIDDEN;
        }
    }

    /**
     * 执行动画
     */
    protected void doAnimation(UriRequest request) {
        // ...
    }
}

0xFF 写在最后

本来还想写一下如何自定义 Activity 启动逻辑的,但是这篇文章实在是有点太长了,所以只好放到下一篇文章里了。

嗯,就这样吧。

暂无评论

发送评论 编辑评论

上一篇
下一篇