从0到1实现一个Android路由(6)——拦截请求再跳转
从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)——拦截请求再跳转相关推荐
- 从0到1实现一个Android路由(1)——初探路由
从0到1实现一个Android路由系列文章 从0到1实现一个Android路由(1)--初探路由 从0到1实现一个Android路由(2)--URL解析器 从0到1实现一个Android路由(3)-- ...
- 虚幻动画 | 让角色动起来,实现一个简易的走、跑、跳状态机
本篇内容将简单介绍如何借助蓝图控制角色,利用现成的素材,从0到1实现一个简易的"走.跑.跳"状态机.目的是让新手更快速清晰地了解虚幻动画系统的运作流程,因此涉及到的内容也比较简单, ...
- XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用
XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用. 关于我 特征 由于是借鉴了ARouter,拥有ARouer所有特征 ...
- xpage 传参_一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用。...
XRouter 一个轻量级的Android路由框架,基于ARouter上进行改良,优化Fragment的使用,可结合XPage使用. 关于我 特征 由于是借鉴了ARouter,拥有ARouer所有特征 ...
- ym——物联网入口之中的一个Android蓝牙4.0
转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! 假设还有同学不知道蓝牙4.0能够做什么请查看Android+蓝牙 4.0 将带来什么? ...
- 关于华为P10(Android 8.0系统)出现的一个莫名奇妙的ANR
关于华为P10(Android 8.0系统)出现的一个莫名奇妙的ANR 首先贴出控制台报出的错误代码: java.util.concurrent.TimeoutException: android.v ...
- 每天学习一个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 ...
- 使用Kotlin打造Android路由框架-KRouter
KRouter(https://github.com/richardwrq/KRouter)路由框架借助gradle插件.kapt实现了依赖注入.为Android平台页面启动提供路由功能. ####从 ...
- android组件化开发视频教程,教你打造一个Android组件化开发框架
作者简介 本篇来自 lucky_billy 的投稿,分享了他的开源组件化框架,详细地讲解框架形成的思路,希望对大家有所帮助. lucky_billy 的博客地址: 解读开源框架设计思想 B站学习视频 ...
最新文章
- mysql从一张表更新另外一张表_MySQL 从一张表update字段到另外一张表中
- [gic]-ARM gicv3/gicv4的详细介绍-2020/08
- C和指针之指针数组和指向数组的指针
- 深入探索 Java 热部署
- MFC 学习笔记(一):MFC单文档程序运行流程梳理与总结
- html css实现登录注册页面,基于HTML5+css+JS_的精美登陆注册界面
- 【英语学习】【Level 08】U01 Let's Read L6 Person of the year
- 第二十节:Scrapy爬虫框架之使用Pipeline存储
- Cocos2d-x简介
- c++读取文本文件里的指定位置的字符_(12)文本文件操作参考
- LeetCode_14_python_最长公共前缀
- 前端json编辑器和富文本编辑器的使用
- 含泪整理最优质平板Rhino犀牛模型素材,你想要的这里都有
- 内燃机设计课设 过量空气系数与温度表对应关系自动查询
- 123456789中间任意加+或-结果等于100
- 泛函分析笔记(十七) 弱偏导数
- Android LruCache和DiskLruCache相结合打造图片加载框架(仿微信图片选择,照片墙)
- Legacy与UEFI
- Matlab + Adobe illustrator科研作图
- Openlookeng Redis Connector 移植