从0到1实现一个Android路由系列文章

  • 从0到1实现一个Android路由(1)——初探路由
  • 从0到1实现一个Android路由(2)——URL解析器
  • 从0到1实现一个Android路由(3)——APT收集路由
  • 从0到1实现一个Android路由(4)——多模块的APT收集路由
  • 从0到1实现一个Android路由(5)——对Kotlin模块的支持
  • 从0到1实现一个Android路由(6)——拦截请求再跳转

在从0到1实现一个Android路由(2)——URL解析器中,提到过请求拦截,其中有个常见的场景是某个页面是需要登录状态的,那么首先要调到登录页,完成了登录之后再跳转到路由页面,但通常登录页都是跳转到主页面的,这该怎么实现呢?上篇文章中没有解决这个问题,本文主要来解决这个问题。

解决这个问题的核心是Hook,接管startActivity(),进行偷梁换柱。因为所有的跳转最终都是通过startActivity来进行的,这里就选择了这么做。关于Hook原理,可以参考Android插件化原理解析——Hook机制之动态代理,本文主要着重说实现。

实现

关于实现,需要考虑的问题是如何保存url,在到了登录界面后,再跳转到原有页面的过程中还能找到先前的url进行跳转。

路由信息的保存与销毁

在拦截成功后,将该URL保存起来;在经过路由跳转的情况下,startActivity之前,清除URL。
EasyRouter的改造如下:

public boolean goToPages(Context context, String url) {boolean find = false;if (TextUtils.isEmpty(url)) {return find;}//判断是否拦截if (routerListener != null && routerListener.onIntercept(url)) {find = true;//保存URLcurrentUrl = url;return find;}。。。for (String key : urlRouterMap.keySet()) {//key肯定是大于等于urlPath的,包含了绝对URL和相对URLif (key.endsWith(urlPath)) {find = true;。。。//消除URLcurrentUrl = null;context.startActivity(intent);break;}}//没有找到if (!find && routerListener != null) {routerListener.onLost(url);}return find;}

Hook实现

参考上面那篇文章的实现,增加了判断EasyRouter中是否有没有处理的URL,如果有,那就交给路由处理一把。

public class InstrumentationHook extends Instrumentation {private Instrumentation base;public InstrumentationHook(Instrumentation base) {this.base = base;}public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {//如果有URL,说明之前拦截过,交给路由继续执行if (!TextUtils.isEmpty(EasyRouter.getInstance().getCurrentUrl())) {EasyRouter.getInstance().goToPages(who, EasyRouter.getInstance().getCurrentUrl());return null;}// 开始调用原始的方法, 调不调用随你,但是不调用的话, 所有的startActivity都失效了.// 由于这个方法是隐藏的,因此需要使用反射调用;首先找到这个方法try {Method execStartActivity = Instrumentation.class.getDeclaredMethod("execStartActivity",Context.class, IBinder.class, IBinder.class, Activity.class,Intent.class, int.class, Bundle.class);execStartActivity.setAccessible(true);return (ActivityResult) execStartActivity.invoke(base, who,contextThread, token, target, intent, requestCode, options);} catch (Exception e) {// 某该死的rom修改了  需要手动适配throw new RuntimeException("do not support!!! pls adapt it");}}
}

Hook

Hook点可以设置在init()方法中,如下:

public boolean init(String scheme, String host) {try {UrlCollector urlCollector = (UrlCollector) Class.forName(URL_COLLECTOR_IMPL_CLASS_NAME).newInstance();urlRouterMap = urlCollector.getUrlRouterMap();this.scheme = scheme;this.host = host;//HookInstrumentationHook.attachContext();return true;}  catch (Exception e) {e.printStackTrace();}return false;}

介绍完了原理后,再来看下demo。

demo

在上个版本的例子中进行增加,增加了一个LoginActivity,有个变量判断是否登录过,然后跳转到MainActivity,MainActivity对路由进行了拦截设置,如果url是启动SecondActivity,那么需要进行登录拦截判断。如下:

override fun onIntercept(url: String?): Boolean {if (url != null && url.startsWith("http")) {startActivity(Intent(this@MainActivity, WebViewActivity::class.java).apply {putExtra("external_url", url)})return true}if ((url == secondActivityUrl || url == dynamicUrl) && !LoginActivity.isLogin) {startActivity(Intent(this@MainActivity, LoginActivity::class.java))return true}return false}

现在来看下效果,启动SecondActivity或DynamicActivity时,会进行登录拦截判断。

这里启动SecondActivity时做了登录拦截,没有登录的时候,出现了登录界面,点击登录按钮后,本应出现MainActivity,但由于hook的原因,跳转到了本应跳转的SecondActivity。从而实现了拦截再跳转。

总结

本文主要是解决前面遗留的问题,拦截跳转的问题,本文使用的方式是Hook,记录需要跳转的路由,再Activity跳转前检测一次,需要的话就交给路由继续处理,从而hook掉原来的跳转。关于本文代码,可以参考master分支

至此,完成了从0到1实现一个Android路由的所有文章,一个好的路由是给别人用的,要有好的API接口,这儿主要是介绍思想,就没有对API接口进行很好的设计。

参考

  • Android插件化原理解析——Hook机制之动态代理

关注我的技术公众号,不定期会有技术文章推送,不敢说优质,但至少是我自己的学习心得。微信扫一扫下方二维码即可关注:

从0到1实现一个Android路由(6)——拦截请求再跳转相关推荐

  1. 从0到1实现一个Android路由(1)——初探路由

    从0到1实现一个Android路由系列文章 从0到1实现一个Android路由(1)--初探路由 从0到1实现一个Android路由(2)--URL解析器 从0到1实现一个Android路由(3)-- ...

  2. 虚幻动画 | 让角色动起来,实现一个简易的走、跑、跳状态机

    本篇内容将简单介绍如何借助蓝图控制角色,利用现成的素材,从0到1实现一个简易的"走.跑.跳"状态机.目的是让新手更快速清晰地了解虚幻动画系统的运作流程,因此涉及到的内容也比较简单, ...

  3. XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用

    XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用. 关于我 特征 由于是借鉴了ARouter,拥有ARouer所有特征 ...

  4. xpage 传参_一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用。...

    XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用. 关于我 特征 由于是借鉴了ARouter,拥有ARouer所有特征 ...

  5. ym——物联网入口之中的一个Android蓝牙4.0

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! 假设还有同学不知道蓝牙4.0能够做什么请查看Android+蓝牙 4.0 将带来什么? ...

  6. 关于华为P10(Android 8.0系统)出现的一个莫名奇妙的ANR

    关于华为P10(Android 8.0系统)出现的一个莫名奇妙的ANR 首先贴出控制台报出的错误代码: java.util.concurrent.TimeoutException: android.v ...

  7. 每天学习一个Android中的常用框架——0.目录

    文章目录 1.前言 2.环境 3.目录 3.1 持久化 3.1.1 Litepal 3.1.2 GreenDao 3.1.3 Realm 3.1.4 DBFlow 3.2 网络传输 3.2.1 OkH ...

  8. 使用Kotlin打造Android路由框架-KRouter

    KRouter(https://github.com/richardwrq/KRouter)路由框架借助gradle插件.kapt实现了依赖注入.为Android平台页面启动提供路由功能. ####从 ...

  9. android组件化开发视频教程,教你打造一个Android组件化开发框架

    作者简介 本篇来自 lucky_billy 的投稿,分享了他的开源组件化框架,详细地讲解框架形成的思路,希望对大家有所帮助. lucky_billy 的博客地址: 解读开源框架设计思想 B站学习视频 ...

最新文章

  1. mysql从一张表更新另外一张表_MySQL 从一张表update字段到另外一张表中
  2. [gic]-ARM gicv3/gicv4的详细介绍-2020/08
  3. C和指针之指针数组和指向数组的指针
  4. 深入探索 Java 热部署
  5. MFC 学习笔记(一):MFC单文档程序运行流程梳理与总结
  6. html css实现登录注册页面,基于HTML5+css+JS_的精美登陆注册界面
  7. 【英语学习】【Level 08】U01 Let's Read L6 Person of the year
  8. 第二十节:Scrapy爬虫框架之使用Pipeline存储
  9. Cocos2d-x简介
  10. c++读取文本文件里的指定位置的字符_(12)文本文件操作参考
  11. LeetCode_14_python_最长公共前缀
  12. 前端json编辑器和富文本编辑器的使用
  13. 含泪整理最优质平板Rhino犀牛模型素材,你想要的这里都有
  14. 内燃机设计课设 过量空气系数与温度表对应关系自动查询
  15. 123456789中间任意加+或-结果等于100
  16. 泛函分析笔记(十七) 弱偏导数
  17. Android LruCache和DiskLruCache相结合打造图片加载框架(仿微信图片选择,照片墙)
  18. Legacy与UEFI
  19. Matlab + Adobe illustrator科研作图
  20. Openlookeng Redis Connector 移植

热门文章

  1. 攻城狮久坐腰疼需要一把好的人体工学椅,附双11人体工学椅开箱体验
  2. 《网络安全:保卫你的数据安全》
  3. android绘制9宫格图片
  4. 谷歌daydream_如果Google Daydream控制器在更新时卡住了怎么办
  5. 2023开学季哪款电容笔值得买?高品质电容笔品牌推荐
  6. 【渝粤教育】广东开放大学 文化传播实务 形成性考核 (38)
  7. HTML 的属性顺序及 CSS的属性声明顺序
  8. 手把手教你用C#写一个刷屏软件
  9. Google智能助理现在可与5,000个智能家居设备配合
  10. 简单的足球胜平负概率计算游戏